标签:code turn line quic ring 快速幂 red lag eve
中文题面
题解:记模m的原根为yg,yg的i次幂mod m(0<=i<=p-2)与1到p-1是有一个一一对应关系的,如果我们相求ab%mod=c%mod,我们可以把a和b换算为对应的\({yg}^{a1}\)\({yg}^{b1}\) = \({yg}^{c1}\),即\({yg}^{(a1+b1)mod(m-1)}\)=\({yg}^{c1}\),因为\({yg}^{(m-1)}\)=1(mod m),相当于(a1+b1)%(m-1)=c1,用对应的数代替一下给出数列里面的数,然后快速幂+fft就行了
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#define LL long long
#define ll long long
#define Redge(u) for (int k = h[u],to; k; k = ed[k].nxt)
#define REP(i,n) for (int i = 1; i <= (n); i++)
#define BUG(s,n) for (int i = 1; i <= (n); i++) cout<<s[i]<<‘ ‘; puts("");
using namespace std;
const int maxn = 32005,maxm = 320005,INF = 1000000000;
const int G = 3,P = 1004535809;
ll n,m,x,s,z;
int L,R[maxn];
LL A[maxn],B[maxn];
ll qpow(ll a,ll b){
ll ans = 1;
for (; b; b >>= 1,a = 1ll * a * a % P)
if (b & 1) ans = 1ll * ans * a % P;
return ans;
}
void NTT(ll* a,int f){
for (int i = 0; i < z; i++) if (i < R[i]) swap(a[i],a[R[i]]);
for (int i = 1; i < z; i <<= 1){
int gn = qpow(G,(P - 1) / (i << 1));
for (int j = 0; j < z; j += (i << 1)){
int g = 1;
for (int k = 0; k < i; k++,g = 1ll * g * gn % P){
int x = a[j + k],y = 1ll * g * a[j + k + i] % P;
a[j + k] = (x + y) % P; a[j + k + i] = (x - y + P) % P;
}
}
}
if (f == 1) return;
int nv = qpow(z,P - 2); reverse(a + 1,a + z);
for (int i = 0; i < z; i++) a[i] = 1ll * a[i] * nv % P;
}
ll yz[50];
ll quickpow(ll a,ll b,ll mod){
ll ans=1;
while(b!=0){
if(b%2==1)ans=ans*a%mod;
a=a*a%mod;
b=b/2;
}
return ans;
}
ll getroot(ll x){
x=x-1;
int cnt=0;
int temp=x;
for(int i=2;i*i<=temp;i++){
if(temp%i==0){
yz[++cnt]=i;
while(temp%i==0)temp=temp/i;
}
}
if(temp>1)yz[++cnt]=temp;
for(int i=2;i<=x;i++){
int flag=0;
for(int j=1;j<=cnt;j++){
if(quickpow(i,x/yz[j],x+1)==1){
flag=1;
break;
}
}
if(flag==0)return i;
}
return -1;
}
ll mp[maxn];
void mul(ll* a,ll* b ,ll* c){
for (int i = 0; i < z; i++) A[i] = a[i];
for (int i = 0; i < z; i++) B[i] = b[i];
for (int i = 0; i < z; i++) R[i] = (R[i >> 1] >> 1) | ((i & 1) << (L - 1));
NTT(A,1); NTT(B,1);
for (int i = 0; i < z; i++) A[i] = 1ll * A[i] * B[i] % P;
NTT(A,-1);
for(int i=0;i<m-1;i++){
c[i]=(A[i]+A[i+m-1])%P;
}
}
ll f[maxn],g[maxn];
int main(){
scanf("%lld %lld %lld %lld",&n,&m,&x,&s);
ll yg=getroot(m);
//printf("%lld\n",yg);
for(int i=0;i<m-1;i++)mp[quickpow(yg,i,m)]=i;
for(int i=1;i<=s;i++){
int temp;
scanf("%d",&temp);
temp=temp%m;
if(temp!=0)
f[mp[temp]]++;
}
g[mp[1]]=1;
L=0;
for (z = 1; z <= 2*m; z <<= 1) L++;
while(n!=0){
if(n%2==1)mul(f,g,g);
mul(f,f,f);
n=n/2;
}
printf("%lld\n",g[mp[x]]);
}
标签:code turn line quic ring 快速幂 red lag eve
原文地址:https://www.cnblogs.com/League-of-cryer/p/14375669.html