BZOJ4818 [Sdoi2017]序列计数
本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作。
本文作者:ljh2000
作者博客:http://www.cnblogs.com/ljh2000-jump/
转载请注明出处,侵权必究,保留最终解释权!
题目链接:BZOJ4818
正解:卷积+快速幂
解题报告:
很simple的一道题,每次转移就是一个卷积,用快速幂优化这个过程。
对于至少有一个质数的限制,用容斥减掉没有质数的情况就好了。
//It is made by ljh2000 //有志者,事竟成,破釜沉舟,百二秦关终属楚;苦心人,天不负,卧薪尝胆,三千越甲可吞吴。 #include <algorithm> #include <iostream> #include <cstring> #include <vector> #include <cstdio> #include <string> #include <queue> #include <cmath> #include <ctime> #define lc root<<1 #define rc root<<1|1 #define rep(i,j,k) for(int i=j;i<=k;i++) #define reg(i,x) for(int i=first[x];i;i=next[i]) using namespace std; typedef long long LL; const int mod = 20170408; const int MAXN = 20000011; int n,m,p,prime[MAXN],cnt; bool vis[MAXN]; LL ans,a[150],b[150],c[150]; inline int getint(){ int w=0,q=0; char c=getchar(); while((c<'0'||c>'9') && c!='-') c=getchar(); if(c=='-') q=1,c=getchar(); while (c>='0'&&c<='9') w=w*10+c-'0',c=getchar(); return q?-w:w; } inline void init(){ vis[1]=1; for(int i=2;i<=m;i++) { if(!vis[i]) { prime[++cnt]=i; } for(int j=1;j<=cnt && prime[j]*i<=m;j++) { vis[i*prime[j]]=1; if(i%prime[j]==0) break; } } } inline void mul(LL *a,LL *b){ memset(c,0,sizeof(c)); int now; for(int i=0;i<p;i++) for(int j=0;j<p;j++) { now=(i+j)%p; c[now]+=a[i]*b[j]; c[now]%=mod; } } inline LL solve(){ int y=n; memset(b,0,sizeof(b)); b[0]=1; while(y>0) { if(y&1) { mul(b,a); for(int i=0;i<p;i++) b[i]=c[i]; } mul(a,a); for(int i=0;i<p;i++) a[i]=c[i]; y>>=1; } return b[0]; } inline void work(){ n=getint(); m=getint(); p=getint(); init(); for(int i=1;i<=m;i++) a[i%p]++; ans=solve(); memset(a,0,sizeof(a)); for(int i=1;i<=m;i++) if(vis[i]) a[i%p]++; ans-=solve(); ans+=mod; ans%=mod; printf("%lld",ans); } int main() { #ifndef ONLINE_JUDGE freopen("count.in","r",stdin); freopen("count.out","w",stdout); #endif work(); return 0; } //有志者,事竟成,破釜沉舟,百二秦关终属楚;苦心人,天不负,卧薪尝胆,三千越甲可吞吴。
本文作者:ljh2000
作者博客:http://www.cnblogs.com/ljh2000-jump/
转载请注明出处,侵权必究,保留最终解释权!