Sdoi2017 序列計數

2021-08-15 16:45:02 字數 1158 閱讀 9509

alice想要得到乙個長度為n的序列,序列中的數都是不超過m的正整數,而且這n個數的和是p的倍數。alice還希望

,這n個數中,至少有乙個數是質數。alice想知道,有多少個序列滿足她的要求。

一行三個數,n,m,p。

1<=n<=10^9,1<=m<=2×10^7,1<=p<=100

一行乙個數,滿足alice的要求的序列數量,答案對20170408取模。

3 5 3

33思路

非常容易想到 o(n*m*p)的轉移 不再贅述

發現不需要列舉每乙個m值 而是可以在一開始就對m分類  (mod p的剩餘系) 分類之後的結果就用c陣列記錄 這樣就可以從i向j轉移即  s[(i+j)%p]+=s[i]*c[j]; o(n*p*p); 還是會t

那麼我們可以構造乙個 s[i][j]的(p*p)的乙個矩陣 表示從i向j轉移的變化 那麼可以定義乙個初始向量 f 表示第乙個位置的選擇方案

明顯的是 f[i]=c[i]; 即分類之後的選擇方案  那麼 f*s就是第二個位置選擇之後每乙個剩餘系的方案數 現在我們可以對s做矩陣快速冪(n-1)次 最後再用f去乘s 之後的 f[0][0]就是不考慮質數的答案ans1

然後在把質數從c中丟擲去  再做一遍 表示沒有質數的方案數ans2  那麼ans1-ans2就是答案

**#include #include #include using namespace std;

typedef long long ll;

const ll mod=20170408;

const int maxn=200+5;

const int n=20000000+5;

int prime[n],tot;

bool visit[n];

int n,m,p;

ll s[maxn][maxn],c[maxn];

struct matrix

matrix operator * (const matrix &p) const

return ans;

}int main()

{ freopen("test.in","r",stdin);

freopen("test.out","w",stdout);

scanf("%d %d %d",&n,&m,&p);

for(int i=0; i

SDOI2017 序列計數

這道題非常的迷幻 首先我們要容斥 考慮記 dp i j 表示前 i 位 p j 的方案數 g i j 表示前 i 位只用合數 p j 的方案數 於是可以考慮最暴力的 dp 是 o nm p 的 但是並沒必要 我們可以提前處理 1 m 這些數 p 的值,用這些值來轉移就好了 也就是額外記乙個 cnt ...

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