SDOI 2015 序列統計

2021-10-01 13:43:25 字數 2084 閱讀 9972

在遭受了巨大的精神打擊後,我決定了,要做乙個壓行的好孩子!!!

部落格如果有不對之處,請一定要指出啊啊啊啊啊謝謝謝謝謝大佬!!!

我們首先可以寫出乙個遞推式:

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]∗f

[c][

d]可以發現,這個格式並不是卷積。那我們怎麼辦呢?

我們知道,有ai∗

aj=a

i+

ja^i*a^j=a^

ai∗aj=

ai+j

,那我們可以將式子轉化為原根i次方。然後我們就可以用卷積來做了。

然後我再來說一下打法:solve函式類似快速冪,每一次乘法相當於新增乙個數(就像dp外層的1至n的迴圈)。而g陣列則表示相應的餘數對應的方案數。

最後,因為運算時不帶取模,我們需要再加上a[i

+m−1

]a[i+m-1]

a[i+m−

1]。為什麼加m-1而不是加m?因為此處保證m為質數,也就是說m的尤拉函式是m-1。(如有不懂尤拉函式的童鞋們可以去康康 )那麼,我們可以保證的是,0到m-2構成的數,在m-1及之後相同的長度還有一毛一樣的。而這取模m-1就是相同的餘數。為什麼只加一次呢?這要看我們變換的範圍。

再最後,我們知道m-1並不一定是階。這就可能有0到m-2之間有重複餘數但不相加的情況。為什麼可以直接輸出呢?仔細看看我們的初始化,我們將輸入的值為餘數處理。實際上,這些不同的編號(i)代表的是同乙個數。

awsl感覺自己在口胡。不知所言。

所以又到了激動人心的上**環節。

#include

#include

using

namespace std;

const

int mod =

1004535809

, n =

50002

;int n, m, x, len, inv, lim =

1, rev[n]

, ori, l, pos =-1

, a[n]

, b[n]

, g[n]

, f[n]

;bool vis[n]

;int

qkpow

(int x,

int y,

int p)

return res;

}int

cal(

const

int p)if(

! flag)

return i;}}

void

swap

(int

&x,int

&y)void

ntt(

int*t,

const

int op)}}

}void

mul(

int*g,

int*f)

void

solve

(int y)

}void

init

(const

int lim)

for(

int i =

0; i < lim;

++ i) rev[i]

=(rev[i >>1]

>>1)

|((i &1)

<<

(l -1)

);}int

main()

init

(m -

1<<1)

;solve

(n);

if(pos !=-1

) cout << g[pos]

% mod;

else cout <<

"0";

putchar

('\n');

return0;

}

謝謝!

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的值...

SDOI2015 序列統計

點此看題 第一次寫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 ...