Problem Description
There is a small set of C \ (S \) , which are elements less than \ (M \) non-negative integer. He wrote a program series generator, may generate a length \ (N \) is the number of columns, each column count are all set \ (S \) .
C with the small generator to generate many of these columns. However, small C has a problem need your help: given integers \ (X \) , require that all can be generated out and meet the product of the number of columns in all the numbers \ (\ bmod M \) is equal to \ (X \) there are the same number of columns how many. Small C that, two columns \ (\ {A_i \} \ ) and \ (\ {B_i \} \ ) different, if and only if there is at least an integer \ (I \) , satisfies \ (A_i \ neq B_i \ ) . In addition, small C think the answer may be large, so he only needs you to help him find the answer \ (\ mod 1004535809 \) value on it.
answer
A good question!
The first sub-section - \ (O (nm ^ 2) \) \ (\ mathrm the DP} {\)
Set \ (dp [i] [j ] \) representative of selected \ (I \) after a film \ (M \) of \ (J \) program number.
Transfer equation: \ (DP [I] [J] = \ SUM \ limits_ {K =. 1} ^ {| S |} {\ SUM \ limits_ {P = 0} ^ {M-. 1} {DP [I-. 1 ] [S_k \ times p \ bmod M]}} \)
Boundary conditions: \ (DP [. 1] [J] = [J \ S in] \)
Time complexity \ (O (nm ^ 2) \) , the desired score \ (10 \) points.
The second sub-class part - \ (O (m ^ 2 \ n-log_2) \) \ (\ mathrm the DP} {\)
Set \ (f [i] [j ] \) representative of selected \ (2 ^ i \) after a film \ (M \) of \ (J \) program number.
Pretreatment \ (f \) after similar solved quickly power can be.
Correct
For the second type sub-section, found in \ (\ SUM \) at a \ (A \ B = C Times \) , the processing is not very good.
Considered for logarithmic, so \ (A = log_g A \) , was \ (A + B = C \) , convolutional, NTT can be optimized.
As to the mapping relationship, film \ (M \) in the sense, depending on the nature of primitive roots, may be converted into logarithmic \ (G {A} ^ \ BMOD M \) , \ (A \) ranges \ ([0, M-. 1) \) .
NTT realized then some details still need to think about.
\(\mathrm{Code}\)
10pts
#include<bits/stdc++.h>
using namespace std;
template <typename Tp>
void read(Tp &x){
x=0;char ch=1;int fh=1;
while(ch!='-'&&(ch>'9'||ch<'0')) ch=getchar();
if(ch=='-') fh=-1,ch=getchar();
while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
x*=fh;
}
const int maxS=8000+7;
const int mod=1004535809;
int n,m,x,S;
int a[maxS];
void Init(void){
read(n);read(m);read(x);read(S);
for(int i=1;i<=S;i++) read(a[i]);
}
int dp[1007][maxS];
void Work(void){
for(int i=1;i<=S;i++) dp[1][a[i]]++;
for(int i=2;i<=n;i++){
for(int j=1;j<=S;j++){
for(int k=0;k<m;k++){
int p=(long long)k*a[j]%m;
dp[i][p]=(dp[i][p]+dp[i-1][k])%mod;
}
}
}
printf("%d\n",dp[n][x]);
}
int main(){
Init();Work();
return 0;
}
60pts
#include<bits/stdc++.h>
using namespace std;
template <typename Tp>
void read(Tp &x){
x=0;char ch=1;int fh=1;
while(ch!='-'&&(ch>'9'||ch<'0')) ch=getchar();
if(ch=='-') fh=-1,ch=getchar();
while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
x*=fh;
}
const int maxS=8000+7;
const int mod=1004535809;
int n,m,x,S;
int a[maxS];
int dp[maxS],opt[maxS];
//bool exist[maxS];
void Init(void){
read(n);read(m);read(x);read(S);
for(int i=1;i<=S;i++) read(a[i]),dp[a[i]]=1;
}
int tmp[maxS];
int power(int x,int p,int mod){
int res(1);
while(p){
if(p&1) res=(long long)res*x%mod;p>>=1;
x=(long long)x*x%mod;
}
return res;
}
void mul(int *f,int *g,int *res){
for(int i=0;i<m;i++){
// if(!exist[i]) continue;
for(int j=0;j<m;j++){
int p=(long long)i*j%m;
tmp[p]=(tmp[p]+(long long)f[i]*g[j]%mod)%mod;
}
}
for(int i=0;i<m;i++) res[i]=tmp[i],tmp[i]=0;
}
void fpow(int p){
while(p){
if(p&1) mul(dp,opt,opt);
mul(dp,dp,dp);p>>=1;
}
}
void Work(void){
opt[1]=1;fpow(n);
printf("%d\n",opt[x]);
}
int main(){
Init();
Work();
return 0;
}
100pts
#include<bits/stdc++.h>
using namespace std;
template <typename Tp>
void read(Tp &x){
x=0;char ch=1;int fh=1;
while(ch!='-'&&(ch>'9'||ch<'0')) ch=getchar();
if(ch=='-') fh=-1,ch=getchar();
while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
x*=fh;
}
const int maxS=16000+7;
const int mod=1004535809;
int n,m,x,S;
int a[maxS];
int dp[maxS<<1],opt[maxS<<1];
int power(int x,int p,int mod){
int res(1);
while(p){
if(p&1) res=(long long)res*x%mod;p>>=1;
x=(long long)x*x%mod;
}
return res;
}
bool check(int g,int p){
int q=p-1;
for(int i=2;(long long)i*i<=q;i++){
if(q%i==0&&(power(g,i,p)==1||power(g,q/i,p)==1)) return false;
}
return true;
}
int getG(int k){
for(int i=2;i<=100;i++) if(check(i,k)) return i;
return -1;
}
int pos[maxS];
int Gm,Gd=3;
int invG=power(Gd,mod-2,mod);
int tr[maxS<<1];
int lim;
void NTT(int *f,int type){
for(int i=0;i<lim;i++) if(i<tr[i]) swap(f[i],f[tr[i]]);
for(int dlen=2;dlen<=lim;dlen<<=1){
int len=dlen>>1,w;
if(type==1) w=power(Gd,(mod-1)/dlen,mod);
else w=power(invG,(mod-1)/dlen,mod);
for(int k=0;k<lim;k+=dlen){
int buf=1;
for(int l=0;l<len;l++){
int LF=f[k+l],RF=(long long)buf*f[len+k+l]%mod;
f[k+l]=(LF+RF)%mod,f[k+l+len]=(LF-RF+mod)%mod;
buf=(long long)buf*w%mod;
}
}
}
if(type==-1){
int inv=power(lim,mod-2,mod);
for(int i=0;i<lim;i++) f[i]=(long long)f[i]*inv%mod;
}
}
void Init(void){
read(n);read(m);read(x);read(S);
Gm=getG(m);
// printf("** GM = %d , invG = %d\n",Gm,invG);
for(int i=0;i<m-1;i++){
int Pos=power(Gm,i,m);
pos[Pos]=i;
}
for(int i=1;i<=S;i++){
read(a[i]);
if(a[i]) dp[pos[a[i]]]++;
}
// for(int i=1;i<=m;i++){
// printf("%d %d\n",dp[i],pos[i]);
// }
}
int tmp[maxS],FF[maxS<<1],GG[maxS<<1];
void mul(int *f,int *g,int *res){
for(int i=0;i<lim;i++) FF[i]=f[i],GG[i]=g[i];
NTT(FF,1);NTT(GG,1);
for(int i=0;i<lim;i++) FF[i]=(long long)FF[i]*GG[i]%mod;
NTT(FF,-1);
for(int i=0;i<m-1;i++) res[i]=(FF[i]+FF[i+m-1])%mod;
}
void fpow(int p){
while(p){
if(p&1) mul(opt,dp,opt);
mul(dp,dp,dp);p>>=1;
}
}
void Work(void){
for(lim=1;lim<=m*2;lim<<=1);
// printf("** lim = %d\n",lim);
for(int i=0;i<lim;i++) tr[i]=(tr[i>>1]>>1)|((i&1)?lim>>1:0);
opt[pos[1]]=1;fpow(n);
printf("%d\n",opt[pos[x]]);
}
int main(){
// printf("**%d\n",getG(12289));
Init();
Work();
return 0;
}