zoukankan      html  css  js  c++  java
  • [BZOJ4818][SDOI2017]序列计数

    bzoj
    luogu

    Description

    Alice想要得到一个长度为(n)的序列,序列中的数都是不超过(m)的正整数,而且这(n)个数的和是(p)的倍数。Alice还希望,这(n)个数中,至少有一个数是质数。Alice想知道,有多少个序列满足她的要求。

    Input

    一行三个数,(n,m,p)
    (1le nle 10^9,1le mle 2*10^7,1le ple 100)

    Output

    一行一个数,满足Alice的要求的序列数量,答案对(20170408)取模。

    Sample Input

    3 5 3

    Sample Output

    33

    sol

    这算是(SDOI)签到题?
    首先至少有一个质数的方案数=总方案数-一个质数都没有的方案数。
    所以筛出(m)以内的质数做两遍就好了。
    注意到原(dp)式是一个卷积的形式,所以可以(O(p^2))直接计算(你要写(MTT)没人拦你)
    所以就做完了,复杂度(O(m+p^2log n))

    code

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    const int N = 2e7+5;
    const int mod = 20170408;
    const int P = 105;
    bool zhi[N];
    int pri[N],tot,n,m,p,f[P],g[P],ans;
    void mul(int *a,int *b){
    	int tmp[P];memset(tmp,0,sizeof(tmp));
    	for (int i=0;i<p;++i)
    		for (int j=0;j<p;++j)
    			(tmp[(i+j)%p]+=1ll*a[i]*b[j]%mod)%=mod;
    	for (int i=0;i<p;++i) a[i]=tmp[i];
    }
    int fastpow(int *a,int *b,int n){
    	for (;n;n>>=1,mul(b,b)) if (n&1) mul(a,b);
    	return a[0];
    }
    int main(){
    	scanf("%d%d%d",&n,&m,&p);
    	zhi[1]=true;
    	for (int i=2;i<=m;++i){
    		if (!zhi[i]) pri[++tot]=i;
    		for (int j=1;j<=tot&&i*pri[j]<=m;++j){
    			zhi[i*pri[j]]=1;
    			if (i%pri[j]==0) break;
    		}
    	}
    	for (int i=1;i<=m;++i) ++g[i%p];
    	f[0]=1;ans=fastpow(f,g,n);
    	memset(f,0,sizeof(f));memset(g,0,sizeof(g));
    	for (int i=1;i<=m;++i) if (zhi[i]) ++g[i%p];
    	f[0]=1;ans=(ans-fastpow(f,g,n)+mod)%mod;
    	printf("%d
    ",ans);return 0;
    }
    
  • 相关阅读:
    js第四天
    js第三天
    js第二天
    面试题集锦;有关作用域和this的指向
    JS高级:事件冒泡和事件捕获;
    关于函数的解析;
    BOM浏览器对象模型;
    关于js动画简单理解;
    关于document的节点;用Dom2创建节点;
    js操作Css样式
  • 原文地址:https://www.cnblogs.com/zhoushuyu/p/9092522.html
Copyright © 2011-2022 走看看