F. Product transformation

来源:互联网 发布:淘宝2元包邮怎么挣钱 编辑:程序博客网 时间:2024/06/06 19:35

嗯,序列写一写可以发现,从最后面开始相邻的差都是杨辉三角。然后走到头,前面还有剩余的话就是2m。啊这里说的是系数。然后我们可以求出循环节来。求出系数来之后先模循环节。循环节其实就是ax==1modm中的x。然后快速幂搞一下就可以了。

#include <bits/stdc++.h>using namespace std;typedef long long LL;const int maxn = 107;const int MAXN = 1e6+7;LL n,m,a,q;LL quick_mod(LL a,LL b,LL mod){    LL ans = 1,base = a%mod;    while(b)    {        if(b & 1)ans = ans*base%mod;        base = base*base%mod;        b >>= 1;    }    return ans;}LL num[MAXN],two[MAXN];void init(LL mod){    num[1] = 1;    for(LL i = 2; i <= m; ++i)    {        num[i] = num[i-1]*i%mod;    }    two[0] = 1;    for(LL i = 1; i <= n; ++i)    {        two[i] = two[i-1]*2%mod;    }}LL C(LL n,LL m,LL mod){    LL ans = num[n];    ans = ans*quick_mod(num[m],mod-2,mod)%mod;    ans = ans*quick_mod(num[n-m],mod-2,mod)%mod;    return ans;}LL ans[MAXN];int main(){    scanf("%I64d%I64d%I64d%I64d",&n,&m,&a,&q);    LL mod = 1;    LL x = a;    for(;; mod++)    {        x %= q;        if(x == 1)break;        x *= a;    }    init(mod);    LL i;    ans[n] = 1;    for(i = n-1; i >= 1; --i)    {        LL p = n-i;        if(p == m)break;        ans[i] = (ans[i+1] + C(m,p,mod))%mod;    }    for(; i >= 1; --i)ans[i] = two[m];    //for(int i = 1; i <= n; ++i)printf("%I64d\n",ans[i]);    for(int i = 1; i <= n; ++i)    {        ans[i] = quick_mod(a,ans[i],q);    }    for(int i = 1; i <= n; ++i)printf("%I64d ",ans[i]);    return 0;}