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;
    }
    
  • 相关阅读:
    登录的验证码
    分页效果
    弹出新窗口
    添加软键盘
    左侧菜单
    制作导航
    DEV第三方控件的GalleryControl控件
    div悬浮在屏幕的中间及点击按钮关闭弹出框
    鼠标经过图片时向前突出并放大图片
    UIImageView实现加载网络gif图片
  • 原文地址:https://www.cnblogs.com/dixiao/p/14851420.html
Copyright © 2011-2022 走看看