【BZOJ4818】[SDOI2017] 序列計數(矩乘水題)


點此看題面

大致題意: 問有多少個長度為\(n\)、其中都是不超過\(m\)的正整數的序列,有至少一個質數,且這\(n\)個數的和是\(p\)的倍數。

前言

一道挺水的題目,然而依然能碼出三個致命錯誤的我還是太菜了。。。

容斥

比較顯然,有至少一個質數的答案就是總答案減去不含質數的答案。

於是這道題就簡單了許多。

動態規划+矩陣優化

考慮設\(f_{i,j}\)表示選擇了\(i\)個數,模\(p\)的余數為\(j\)的方案數,則每次只要枚舉一個可選的數就能進行轉移。

而看到\(n\)這么大,\(p\)卻只有\(100\),很自然就想到矩乘。

建出轉移矩陣,其中第\(i\)行第\(j\)列表示從余數為\(i\)轉移到余數為\(j\)的方案數,顯然答案就是轉移矩陣的\(n\)次冪第\(0\)行第\(0\)列的值。

在建立總答案的轉移矩陣時,可以枚舉余數\(i\),計算出\(1\sim m\)中模\(p\)\(i\)的數的個數就是\(\frac{m-i}p+[i\not=0]\)(之所以\(i\not=0\)時才加\(1\),是因為\(0\)不是正整數)。然后將每個\((j,(i+j)\%p)\)加上這一個數。

在建立不含質數的轉移矩陣時,可以直接枚舉質數,在總答案轉移矩陣的基礎上減去貢獻。

具體實現詳見代碼。

代碼

#include<bits/stdc++.h>
#define Tp template<typename Ty>
#define Ts template<typename Ty,typename... Ar>
#define Reg register
#define RI Reg int
#define Con const
#define CI Con int&
#define I inline
#define W while
#define X 20170408
#define Inc(x,y) ((x+=(y))>=X&&(x-=X))
using namespace std;
int n,m,p;
class LinearSieve
{
	private:
		#define SZ 20000000
		int P[SZ+5];
	public:
		int Pt;I int operator [] (CI x) {return P[x];}
		I LinearSieve()//線性篩篩質數
		{
			for(RI i=2,j;i<=SZ;++i) for(!P[i]&&(P[++Pt]=i),
				j=1;j<=Pt&&i*P[j]<=SZ;++j) if(P[i*P[j]]=1,!(i%P[j])) break;
		}
}S;
struct M//矩陣
{
	#define P 100
	int a[P+5][P+5];I int *operator [] (CI x) {return a[x];}
	I M() {for(RI i=0,j;i^p;++i) for(j=0;j^p;++j) a[i][j]=0;}
	I friend M operator * (Con M& x,Con M& y)//矩陣乘法
	{
		M t;for(RI i=0,j,k;i^p;++i) for(j=0;j^p;++j)
			for(k=0;k^p;++k) t[i][j]=(1LL*x.a[i][k]*y.a[k][j]+t[i][j])%X;return t;
	}
	I friend M operator ^ (M x,RI y)//矩陣快速冪
	{
		M t;for(RI i=0;i^p;++i) t[i][i]=1;W(y) y&1&&(t=t*x,0),x=x*x,y>>=1;return t;
	}
}U;
int main()
{
	RI i,j,t,ans;scanf("%d%d%d",&n,&m,&p);
	for(i=0;i^p&&i<=m;++i) for(t=(m-i)/p+(i!=0),j=0;j^p;++j) Inc(U[j][(i+j)%p],t);//計算總答案
	for(ans=(U^n)[0][0],i=1;i<=S.Pt&&S[i]<=m;++i)
		for(j=0;j^p;++j) !U[j][(S[i]+j)%p]--&&(U[j][(S[i]+j)%p]+=X);//計算不含質數答案
	return ans=(ans-(U^n)[0][0]+X)%X,printf("%d\n",ans),0;
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM