• luogu 3702 [SDOI2017]序列计数 矩阵乘法+容斥


    现在看来这道题真的不难啊~

    正着求不好求,那就反着求:答案=总-全不是质数 

    这里有一个细节要特判:1不是质数,所以在算全不是质数的时候要特判1 

    code: 

    #include <bits/stdc++.h>           
    #define N 104 
    #define M 20000002 
    #define mod 20170408    
    #define ll long long  
    #define setIO(s) freopen(s".in","r",stdin) 
    using namespace std;  
    int n,m,p,tot; 
    int cnt[N];
    bool vis[M];
    int prime[200000],cnt2[N];  
    struct matrix 
    {   
        ll a[100][100];               
        void re() { memset(a,0,sizeof(a));}  
        void I() { re(); for(int i=0;i<p;++i) a[i][i]=1ll;  }
        ll*operator[](int x) { return a[x]; }                       
    }A,B;   
    matrix operator*(matrix a,matrix b) 
    {    
        matrix c;c.re();           
        int i,j,k; 
        for(i=0;i<p;++i) 
        {
            for(j=0;j<p;++j)
                for(k=0;k<p;++k) 
                    c[i][j]=(c[i][j]+a[i][k]*b[k][j]%mod+mod)%mod;   
        }   
        return c;      
    }
    matrix operator^(matrix a,ll k) 
    {   
        matrix tmp;                    
        for(tmp.I();k;k>>=1,a=a*a) if(k&1) tmp=tmp*a;   
        return tmp;      
    }
    int main() 
    { 
        // setIO("input");           
        int i,j; 
        scanf("%d%d%d",&n,&m,&p);        
        for(i=1;i<=m;++i) cnt[i%p]++;        
        for(i=2;i<=m;++i) 
        {   
            if(!vis[i]) prime[++tot]=i;  
            for(j=1;j<=tot&&prime[j]*i<=m;++j) 
            {
                vis[i*prime[j]]=1;  
                if(i%prime[j]==0) break;       
            }         
        }    
        for(i=1;i<=m;++i) if(vis[i]) ++cnt2[i%p]; 
        ++cnt2[1%p];                            
        A.re();          
        B.re();    
        for(i=0;i<p;++i) 
        {
            for(j=0;j<p;++j) 
            {
                int pp=(j-i+p)%p;        
                A[i][j]=cnt[pp];                            
                B[i][j]=cnt2[pp];                                 
            }
        }                      
        A=A^n;       
        B=B^n;          
        // printf("%lld %lld
    ",A[0][0],B[0][0]);   
        printf("%lld
    ",(A[0][0]-B[0][0]+mod)%mod);        
        return 0;
    }
    

      

  • 相关阅读:
    C#处理json实战
    HDU3994(Folyd + 期望概率)
    POJ1270 Following Orders (拓扑排序)
    HDU 3634 City Planning (离散化)
    HDU4762(JAVA大数)
    POJ3026(BFS + prim)
    POJ1679(次小生成树)
    UVA10487(二分)
    ZOJ 2048(Prim 或者 Kruskal)
    FZU 1856 The Troop (JAVA高精度)
  • 原文地址:https://www.cnblogs.com/guangheli/p/11663406.html
Copyright © 2020-2023  润新知