bzoj3992 SDOI2015 序列統計

2022-05-02 05:24:07 字數 2671 閱讀 6128

小c有乙個集合s,裡面的元素都是小於m的非負整數。他用程式編寫了乙個數列生成器,可以生成乙個長度為n的數列,數列中的每個數都屬於集合s。

小c用這個生成器生成了許多這樣的數列。但是小c有乙個問題需要你的幫助:給定整數x,求所有可以生成出的,且滿足數列中所有數的乘積mod m的值等於x的不同的數列的有多少個。小c認為,兩個數列和不同,當且僅當至少存在乙個整數i,滿足ai≠bi。另外,小c認為這個問題 的答案可能很大,因此他只需要你幫助他求出答案mod 1004535809的值就可以了。

一行,四個整數,n、m、x、|s|,其中|s|為集合s中元素個數。第二行,|s|個整數,表示集合s中的所有元素。

一行,乙個整數,表示你求出的種類數mod 1004535809的值。

4 3 1 2

1 28

【樣例說明】

可以生成的滿足要求的不同的數列有(1,1,1,1)、(1,1,2,2)、(1,2,1,2)、(1,2,2,1)、(2,1,1,2)、(2,1,2,1)、(2,2,1,1)、(2,2,2,2)。

【資料規模和約定】

對於10%的資料,1<=n<=1000;

對於30%的資料,3<=m<=100;

對於60%的資料,3<=m<=800;

對於全部的資料,1<=n<=109,3<=m<=8000,m為質數,1<=x<=m-1,輸入資料保證集合s中元素不重複

正解:$dp$+$ntt$。

首先考慮暴力$dp$,$f[i][j]$表示統計到第$i$位,乘積為$j$的方案數,然後很顯然,$f[i][(k*p)\mod m]=f[i-1][k]*sum[p]$,其中$sum[p]$為p這個數出現的次數。

但是這樣是肯定會$t$飛的,所以我們考慮優化。話說這個優化還是蠻玄學的。。

我們可以把乘法變成加法,然後兩個數相乘就是它們的對數相加,當然底數要相同,並且對數肯定要是整數。

因為$m$是質數,所以$m$必定有原根。我們又知道,原根的$[1,m-1]$次方對應了$[1,m-1]$這些數,所以我們可以求出$[1,m-1]$的離散對數,也就是使得原根$g^=i$的$x$(然而我沒學過所以不會。。)

設$ind[i]$為$i$在模$m$意義下的離散對數,於是$f[i][(ind[k]+ind[p])\mod (m-1)]=f[i-1][ind[k]]*sum[ind[p]]$(注意這裡第二維的取值範圍是$m-1$,所以還要加乙個特判)

因為答案對$1004535809$取模,所以顯然這個方程可以用$ntt$優化,但是$n$的範圍很大,有$10^$級別,不過我們在卷積外面套乙個快速冪就行了。

我們先用快速冪算出$sum$的$n$次方,然後再用$f[0]*sum$,最後輸出$f[n][ind[x]]$,就是我們所要的答案。

1

//it is made by wfj_2048~

2 #include 3 #include 4 #include 5 #include 6 #include 7 #include 8 #include 9 #include 10 #include 11 #include 12 #include 13 #include

14#define rhl (1004535809)

15#define inf (1<<30)

16#define nn (100010)

17#define g (3)

18#define il inline

19#define rg register

20#define ll long long

21#define file(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout)

2223

using

namespace

std;

2425

intrev[nn],ind[nn],n,n,m,x,s,lg,gg;

26ll ans[nn],a[nn],b[nn],sum[nn];

2728 il int

gi()

3536

il ll qpow(rg ll a,rg ll b)

42return

ans;43}

4445 il void ntt(ll *a,rg int n,rg int

f)55}56

}57if (f==1) return; reverse(a+1,a+n); rg ll inv=qpow(n,rhl-2

);58

for (rg int i=0;irhl;

59for (rg int i=m;i1) ? i%(m-1) : m-1]+=a[i])%=rhl,a[i]=0; return;60

}6162 il void nttpow(ll *a,rg int

b)71

for (rg int i=0;irhl;

72 ntt(a,n,-1); b>>=1;73

}74for (rg int i=0;ireturn;75

}7677 il int isroot(rg int

x)83

return1;

84}8586 il void

pre()

88 rg int l=1; for (rg int i=1;ireturn;89

}9091 il void

work()

100101

intmain()

bzoj3992 SDOI2015 序列統計

time limit 30 sec memory limit 128 mb submit 673 solved 327 submit status discuss 小c有乙個集合s,裡面的元素都是小於m的非負整數。他用程式編寫了乙個數列生成器,可以生成乙個長度為n的數列,數列中的每個數都屬於集合s。...

bzoj3992 SDOI2015 序列統計

不好做不好做,真心不好做。這個題顯然是dp,一開始我們這樣設計狀態f i j 表示長度為i的序列,積在模 m 意義下等於 j的數列的方案數。那顯然直接做的複雜度是o nm2 到了這裡,有一種矩陣快速冪做法,可以直接優化到o nm3 應該能過30 顯然正解不允許帶有o m3 所以矩陣肯定是不行了。到這...

BZOJ3992 SDOI2015 序列統計

小c有乙個集合s,裡面的元素都是小於m的非負整數。他用程式編寫了乙個數列生成器,可以生成乙個長度為n的數列,數列中的每個數都屬於集合s。小c用這個生成器生成了許多這樣的數列。但是小c有乙個問題需要你的幫助 給定整數x,求所有可以生成出的,且滿足數列中所有數的乘積mod m的值等於x的不同的數列的有多...