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

    考虑处理如下两个条件:

    1. 和为(p)的倍数
    2. 有至少一个质数

    考虑正难则反的原则,至少一个质数很难算的,我们考虑求出所有满足条件一的,还有仅由合数满足条件一的个数。

    (f_{i,x})为取了(i)个,(mod p = x)的方案数
    那拼接一下(f_{i + j,x} = sum_{a + b = x(mod p)}f_{i,a}f_{j,b})
    考虑生成函数,那么上面这个操作等于循环卷积,那么(log(n))次循环卷积就可以做了。
    因为(p)太小,所以直接暴力卷。

    [SDOI2017]序列计数
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #define ll long long
    #define N 20000005
    #define M 200
    #define mod 20170408
    
    ll n,m,p;
    bool P[N];
    
    ll f[200],g[200],F[200],G[200];
    
    inline void sieve(){
    	P[1] = 0;
    	for(int i = 2;i <= N;++i){
    		if(P[i]){
    			for(int j = 2;j * i <= N;++j)
    			P[i * j] = 0;
    		}
    	}
    }
    
    ll c[M * 2];
    
    inline void mul(ll *a,ll *b){
    	for(int i = 0;i < p;++i)
    	for(int j = 0;j < p;++j)
    	c[i + j] = (c[i + j] + a[i] * b[j]) % mod;
    	for(int i = 0;i < p;++i)
    	a[i] = (c[i] + c[i + p]) % mod,c[i] = c[i + p] = 0;
    }
    
    inline void powf(ll k){
    	F[0] = 1;
    	while(k){
    //		for(int i = 0;i < p;++i)
    //		std::cout<<f[i]<<" ";		
    		if(k & 1)mul(F,f);
    		mul(f,f);
    		k >>= 1;
    	}
    }
    
    inline void powg(ll k){
    	G[0] = 1;
    	while(k){
    		if(k & 1)mul(G,g);
    		mul(g,g);
    		k >>= 1;
    	}
    }
    
    int main(){
    	std::memset(P,1,sizeof(P));
    	scanf("%lld%lld%lld",&n,&m,&p);
    	sieve();
    	for(int i = 1;i <= m;++i)
    	f[i % p] ++ ;
    	powf(n);
    	for(int i = 1;i <= m;++i)
    	if(!P[i])
    	g[i % p] ++ ;	
    	powg(n);	
    	std::cout<<(F[0] - G[0] + mod) % mod;
    }
    
  • 相关阅读:
    1.12学习总结:分区
    1.11学习总结:持久化
    1.10学习总结:RDD的行动操作
    1.9学习总结:RDD的转换操作
    1.8学习总结:RDD创建
    1.7学习总结:pyspark实例WordCount
    1.6学习总结:Spark集群的高可用配置
    1.5学习总结:安装Spark
    毕业设计第四周第七天完成情况汇总
    毕业设计第四周第五天完成情况汇总
  • 原文地址:https://www.cnblogs.com/dixiao/p/14851420.html
Copyright © 2011-2022 走看看