點此看題
第一次寫ntt
\text
ntt,被搞自閉了。
0x01 樸素dp
設f [i
][j]
f[i][j]
f[i][j
]為選i
ii個數乘積為j
jj的方案數,轉移如下:
f [2
i][j
]=f[
i][k
]×f[
i][j
×inv
k]
f[2i][j]=f[i][k]\times f[i][j\times inv_k]
f[2i][
j]=f
[i][
k]×f
[i][
j×in
vk]
這個轉移是無法優化的,時間複雜度o
(logn
m2
)o(\log nm^2)
o(lognm2
),無法優化。
受到這道題的啟發,我們需要把乘轉化為加然後套卷積。
0x02 原根的引入
對於乙個質數m
mm,如果gi%
mg^i\%m
gi%m
,i
ii取[0,
m−2]
[0,m-2]
[0,m−2
],gg
g兩兩不同,那麼就稱g
gg是m
mm的乙個原根,原根有很多神奇的性質,比如:gi×
gj=g
i+
jg^i\times g^j=g^
gi×gj=
gi+j
,g m−
1=
1g^=1
gm−1=1
我們可以利用原根,重新定義dpdp
dp方程,f[i
][j]
f[i][j]
f[i][j
]為選i
ii個數,它們的乘積所對應的原根指數為j
jj,轉移如下:
f [2
i][j
]=f[
i][k
]+f[
i][(
j−k+
m−1)
%(m−
1)
]f[2i][j]=f[i][k]+f[i][(j-k+m-1)\%(m-1)]
f[2i][
j]=f
[i][
k]+f
[i][
(j−k
+m−1
)%(m
−1)]
這個方程就可以用卷積來優化,由於這道題要膜1004535809
1004535809
100453
5809
,我們選擇ntt
\text
ntt。
現在還有乙個問題,就是如何求原根,由於aφ(
m)=1
modm
a^=1\mod m
aφ(m)=
1mod
m,所以φ(m
)\varphi(m)
φ(m)
是乙個迴圈節,原根就要滿足[0,
m−2]
[0,m-2]
[0,m−2
]中沒有迴圈節,而更小的迴圈節一定存在於φ(m
)\varphi(m)
φ(m)
的因數中,列舉所有數作為可能的原根,在列舉φ(m
)\varphi(m)
φ(m)
所有的因數判斷迴圈節,就可以找出原根,這也是這道題m
mm很小並且是質數的原因。
0x03 tips
這道題資料有鍋,輸入的0
00要被忽略。
#include
#include
#include
#define int long long
using
namespace std;
const
int maxn =
20005
;const
int mod =
1004535809
;int
read()
int n,m,x,s,g,mp[maxn]
,a[maxn]
,b[maxn]
,r[maxn]
,rev[maxn]
;int
qkpow
(int a,
int b,
int mod=mod)
return res;
}int
get_rt
(int x)
if(phi>
1) fac[
++tot]
=phi;
phi=x-1;
for(
int i=
2;i<=phi;i++
)return0;
}void
ntt(
int*a,
const
int len,
int tmp)
for(
int s=
2;s<=len;s<<=1)
}}if(tmp==1)
return
;int inv=
qkpow
(len,mod-2)
;for
(int i=
0;i) a[i]
=a[i]
*inv%mod;
}void
mul(
int*a,
int*b,
int*c)
,b[maxn]
=,len=1;
while
(len<=
2*m) len<<=1;
for(
int i=
0;i1;i++
) a[i]
=a[i]
;for
(int i=
0;i1;i++
) b[i]
=b[i]
;ntt
(a,len,1)
;ntt
(b,len,1)
;for
(int i=
0;i) a[i]
=a[i]
*b[i]
%mod;
ntt(a,len,-1
);for(
int i=
0;i1;i++
) c[i]
=(a[i]
+a[i+m-1]
)%mod;
}signed
main()
while
(n>0)
//多項式的快速冪,優化dp
printf
("%lld\n"
,r[mp[x]])
;}
SDOI2015 序列統計
time limit 30 sec memory limit 128 mb submit 1829 solved 870 submit status discuss 小c有乙個集合s,裡面的元素都是小於m的非負整數。他用程式編寫了乙個數列生成器,可以生成乙個長度為n的數 列,數列中的每個數都屬於集合...
SDOI2015 序列統計
description 小c有乙個集合s,裡面的元素都是小於m的非負整數。他用程式編寫了乙個數列生成器,可以生成乙個長度為n的數列,數列中的每個數都屬於集合s。小c用這個生成器生成了許多這樣的數列。但是小c有乙個問題需要你的幫助 給定整數x,求所有可以生成出的,且滿足數列中所有數的乘積mod m的值...
SDOI 2015 序列統計
在遭受了巨大的精神打擊後,我決定了,要做乙個壓行的好孩子!部落格如果有不對之處,請一定要指出啊啊啊啊啊謝謝謝謝謝大佬!我們首先可以寫出乙個遞推式 f a c b d取 模mod f a b f c d f a c b d取模mod f a b f c d f a c b d 取模mo d f a b...