[ASDFZ]方程+取石子


方程

Description
给定正整数a,b,c,你需要求出有多少个系数为非负整数的多项式 f 满足 f(a)=b,f(b)=c 并给出一组解。有多组数据。

Input
第一行一个正整数 t 表示数据组数。
接下来 t 行每行三个正整数

a,b,c。
Output
对于每组数据, 第一行输出满足条件的多项式的个数对998244353取模的结果。若满足条件的多项式有无穷多个,输出-1。若个数>0且取模结果为 0,则输出 998244353。
若第一行输出的结果不为 0 或-1,那么另起一行,输出所有满足条件的多项式中次数最高的那个多项式,如果有多个多项式次数最高,那么输出将系数从高到低排列成数列后,字典序最大的那个。
输出多项式时,第一个数为一个非负整数 n ,表示该多项式的次数,接下来 n+1 个非负整数,为该多项式各个次数前的系数,按次数从高到低排列。

Sample Input

2
2 2 2
2 3 3

Sample Output

2
1 1 0
1
0 3

HINT
\(1\leq{t}\leq100,1\leq{a,b,c}\leq10^{18}\).

Solution

100分

如果 \(b=1\) , 如果 \(a=b=c=1\) , 有无穷解 ; 如果 \(b=c=1,a>1\) , 只有 \(f(x)=1\) 是满足条件的 ; 除此之外,无解.

\(b>1\) 时, 设常数项为 \(d'\) ,发现 \(bk+d'=c\) , 所以设 \(d\equiv{c}(mod\;b)\) .

\(d>0\) , 则常数项为\(d\) ; 否则,常数项为 \(0\)\(b\) .

如果为 \(b\) 的话 , 则 \(f(a)\geq{b}\) 了 , \(f\) 是唯一确定的 .

确定常数项后 , 递归\(\frac{b-d}{a}\)\(\frac{c-d}{b}\)即可 .

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define N 70
using namespace std;
typedef long long ll;
int t,mx,tot;
ll f[N],a,b,c;
inline int read(){
    int ret=0;char c=getchar();
    while(!isdigit(c))
        c=getchar();
    while(isdigit(c)){
        ret=(ret<<1)+(ret<<3)+c-'0';
        c=getchar();
    }
    return ret;
}
inline void func(ll x,ll y){
    if(!x||!y){
        if(!x&&!y) ++tot;
        return;
    }
    if(y%b){
        if(!((x-y%b)%a)){
            f[++mx]=y%b;
            func((x-y%b)/a,y/b);
        }
    }
    else{
        int p=mx;
        if(!(x%a)){
            f[++mx]=0;
            func(x/a,y/b);
        }
        if(x==y) 
            if((++tot)==1){
                mx=p;f[++mx]=x;
            }
    } 
}
inline void Aireen(){
    scanf("%d",&t);
    while(t--){
        scanf("%lld%lld%lld",&a,&b,&c);
        if(b==1)
            if(c==1)
                if(a==1) puts("-1");
                else printf("1\n0 1\n");
            else puts("0");
        else{
            tot=0;mx=-1;
            func(b,c);
            printf("%d\n",tot);
            if(tot){
                printf("%d",mx); 
                for(int i=mx;i>=0;--i)
                    printf(" %lld",f[i]);
                printf("\n");
            } 
        }
    }
}
int main(){
    freopen("equation.in","r",stdin);
    freopen("equation.out","w",stdout);
    Aireen();
    fclose(stdin);
    fclose(stdout);
    return 0;
}

取石子

Description
给定一棵大小为 n 的树,第 i 个结点上有 \(a_i\) 个石子。
方方方首先在一个结点上放上一个旗子,然后方方方和蛤布斯依次操作,每次从旗子所在结点上移除 1 至 k 个石子,然后将旗子移到一个相邻的结点上。
如果旗子所在结点没有石子,则当前操作的人输。
你需要求出方方方在哪些结点上放旗子可以获胜。
Input
第一行两个正整数 n,k。
第二行 n 个正整数 \(a_i\)
接下来 n-1 行每行两个整数 u,v 表示一条边。
Output
第一行一个整数 m 表示可以获胜的结点数量。
第二行 m 个整数表示结点,从小到大排序后输出。
Sample Input

2 233
1 2
1 2

Sample Output

1
2

HINT
Solution

100分

显然,把石子移到石子数\(\geq\)当前结点的点上是没有用的,因为对方还可以将旗子移回来.
将所有点按石子数排序后,DP胜负态即可.

#include
#include
#include
#include
#include
#include
#include
#include
#define N 100005
#define min(a,b) (ab?a:b)
using namespace std;
typedef long long ll;
struct graph{
    int nxt,to;
}e[N<<1];
int a[N],g[N],f[N],p[N],ans[N],n,k,cnt,tot;
inline void addedge(int x,int y){
    e[++cnt].nxt=g[x];g[x]=cnt;e[cnt].to=y;
}
inline bool cmp(int x,int y){
    return a[x]

2017-04-20 20:19:01