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