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

    Description:

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

    Hint:

    (20\%)的数据,(1leq n,mleq100)
    (50\%)的数据,(1leq m leq 100)
    (80\%)的数据,(1leq mleq 10^6)
    (100\%)的数据,(1leq n leq 10^9,1leq m leq 2 imes 10^7,1leq pleq 100)

    Solution:

    非正解A掉的....

    考虑构造生成函数

    设多项式 (x^i) 项的系数表示总和模p为i的序列的方案数

    观察到p非常小,把多项式暴力乘起来,快速幂优化一下就过了??

    至于最少有一个素数的约束,不太好算,就转化一下,求所有方案-不含素数的方案

    #include <map>
    #include <set>
    #include <stack>
    #include <cmath>
    #include <queue>
    #include <cstdio>
    #include <cstring>
    #include <cstdlib>
    #include <iostream>
    #include <algorithm>
    #define ls p<<1 
    #define rs p<<1|1
    using namespace std;
    typedef long long ll;
    const int mxn=2e7+5,mod=20170408;
    int n,m,p,tot,pr[8000000],vis[mxn];
    
    inline int read() {
        char c=getchar(); int x=0,f=1;
        while(c>'9'||c<'0') {if(c=='-') f=-1;c=getchar();}
        while(c<='9'&&c>='0') {x=(x<<3)+(x<<1)+(c&15);c=getchar();}
        return x*f;
    }
    inline int chkmax(int &x,int y) {if(x<y) x=y;}
    inline int chkmin(int &x,int y) {if(x>y) x=y;}
    
    struct ed {
        int to,nxt;
    }t[mxn<<1];
    
    struct poly {
        int x[205];
        poly() {
            memset(x,0,sizeof(x));
        }
        friend poly operator * (poly a,poly b) {
            poly res;
            for(int i=0;i<p;++i) 
                for(int j=0;j<p;++j) 
                    (res.x[(i+j)%p]+=1ll*a.x[i]*b.x[j]%mod)%=mod;
            return res;
        }
    }U,C;
    
    void sieve() { //m在线性范围内,可以直接筛
        vis[1]=1; 
        for(int i=2;i<=m;++i) {
            if(!vis[i]) pr[++tot]=i;
            for(int j=1;j<=tot&&i*pr[j]<=m;++j) {
                vis[pr[j]*i]=1;
                if(i%pr[j]==0) break ;
            }
        }
    }
    
    void init() 
    {
        for(int i=1;i<=m;++i) {
            ++U.x[i%p];
            if(vis[i]) ++C.x[i%p]; //分别预处理
        }
    }
    
    poly qpow(poly bs,int b) 
    {
        poly res=bs; --b;
        while(b) {
            if(b&1) res=res*bs;
            bs=bs*bs;
            b>>=1;
        }	
        return res;
    }
    
    int main()
    {
        n=read(); m=read(); p=read(); 
        sieve(); init(); U=qpow(U,n); C=qpow(C,n);
        printf("%d",(U.x[0]-C.x[0]+mod)%mod);
        return 0;
    }
    
    
  • 相关阅读:
    二叉树的最大深度与最小深度
    【C++学习笔记】由 const char* 引出的一系列问题
    【C++学习笔记】标准库容器Vector可变长度实现原理
    Python数据可视化之Matplotlib学习笔记
    python读取excel文件—xlrd
    ubuntu14.04下嵌入式工作环境搭建
    ubuntu14.04下交叉编译器的安装
    挂载nfs系统问题之: Root-NFS: Server returned error -13 while mounting
    关于开发板不能ping通外网IP
    Socket的协议地址属性
  • 原文地址:https://www.cnblogs.com/list1/p/10545864.html
Copyright © 2011-2022 走看看