SDOI2017 序列計數

2022-04-08 08:05:44 字數 1540 閱讀 3480

這道題非常的迷幻

首先我們要容斥

考慮記\(dp[i][j]\)表示前\(i\)位\(\%p=j\)的方案數

\(g[i][j]\)表示前\(i\)位只用合數\(\%p=j\)的方案數

於是可以考慮最暴力的\(dp\)是\(o(nm^*p)\)的

但是並沒必要

我們可以提前處理\(1-m\)這些數\(\%p\)的值,用這些值來轉移就好了

也就是額外記乙個\(cnt[i]\)表示\(\%p\)為\(i\)的數量和\(comp[i]\)表示\(\%p\)為\(i\)的合數的數量

於是就沒必要列舉\(1-m\)轉移了

複雜度變成\(o(np^2)\)

實際上這個序列的生成與位置無關

也就是說我們可以倍增的處理

\(dp[n][j]\)可以由\(dp[n/2][j]\)來直接轉移

於是遞迴做就好了

複雜度\(o(p^2\log n)\)

然而因為轉移的形式是乙個卷積的模樣

所以是可以做到\(o(p\log p\log n)\)的

但是出題人又不卡,就沒寫...

#includeusing namespace std;

#define rep( i, s, t ) for( register int i = s; i <= t; ++ i )

#define re register

#define int long long

int read()

while(cc >= '0' && cc <= '9') cn = cn * 10 + cc - '0', cc = getchar();

return cn * flus;

}const int p = 20170408 ;

const int n = 2000000 + 5 ;

const int m = 100 + 5 ;

const int r = 2 * 1e7 + 5 ;

int n, m, p, dp[2][m], g[2][m], cnt[m], comp[m], ed ;

int pr[n], top;

bool isp[r];

void init() }}

void f( int x, int w )

f( x / 2, w ^ 1 ) ;

rep( j, 0, ed ) dp[w][j] = 0, g[w][j] = 0 ;

rep( j, 0, ed ) rep( k, 0, ed )

dp[w][j] = ( dp[w ^ 1][k] * dp[w ^ 1][(p + j - k) % p] % p + dp[w][j] ) % p ;

rep( j, 0, ed ) rep( k, 0, ed )

g[w][j] = ( g[w ^ 1][k] * g[w ^ 1][(p + j - k) % p] % p + g[w][j] ) % p ;

if( x & 1 )

}signed main()

Sdoi2017 序列計數

alice想要得到乙個長度為n的序列,序列中的數都是不超過m的正整數,而且這n個數的和是p的倍數。alice還希望 這n個數中,至少有乙個數是質數。alice想知道,有多少個序列滿足她的要求。一行三個數,n,m,p。1 n 10 9,1 m 2 10 7,1 p 100 一行乙個數,滿足alice的...

Sdoi2017 序列計數

time limit 30 sec memory limit 128 mb submit 317 solved 210 alice想要得到乙個長度為n的序列,序列中的數都是不超過m的正整數,而且這n個數的和是p的倍數。alice還希望 這n個數中,至少有乙個數是質數。alice想知道,有多少個序列滿...

SDOI2017 序列計數

alice 想要得到乙個長度為 n 的正整數序列 滿足 alice 想知道,有多少個序列滿足她的要求。由於題目有 n 個數 和 有否質數 這三個主要限制,因此 設 f i,j,1 0 表示前 i 個數,和為 j 是否有了乙個質數。列出樸素 dp 方程 f i,j,0 sum f i 1,j k,0 ...