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

    [题目链接]

            https://www.lydsy.com/JudgeOnline/problem.php?id=4818

    [算法]

            考虑容斥 , 用有至少有一个质数的合法序列数 - 没有质数的合法序列数

            这两个问题是等价的 , 为方便讨论 , 我们考虑前者该如何计算 :

            用fi , j表示前i个数 , 模p余j的合法序列数

            显然有fi , j = sigma{ fi - 1 , j - k }

            矩阵优化即可

            时间复杂度 : O(M + logN)

    [代码]

            

    #include<bits/stdc++.h>
    using namespace std;
    
    #ifndef LOCAL
        #define eprintf(...) fprintf(stderr , _VA_ARGS)
    #else
        #define eprintf(...) 42
    #endif
    
    typedef long long ll;
    typedef long double ld;
    typedef vector< int > vi;
    typedef pair<int , int> pii;
    typedef pair<ll , int> pli;
    typedef pair<ll , ll> pll;
    typedef unsigned long long ull;
    #define mp make_pair
    #define fi first
    #define se second
    const int N    = 2e7 + 10;
    const int P = 20170408;
    
    struct Tmatrix {
        int mat[110][110];
    } a;
    
    int n , m , p , tot;
    int prime[N] , sa[110] , sb[110];
    bool lab[N] , f[N];
    
    template <typename T> inline void chkmax(T &x , T y) { x = max(x , y); }
    template <typename T> inline void chkmin(T &x , T y) { x = min(x , y); }
    template <typename T> inline void read(T &x) {
        T f = 1; x = 0;
        char c = getchar();
        for (; !isdigit(c); c = getchar()) if (c == '-') f = -f;
        for (; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + c - '0';
        x *= f;
    }
    inline void sieve( ) {
        for (int i = 2; i <= m; ++i) {
            if (!f[i]) {
                prime[++tot] = i;
                lab[i] = true;    
            }
            for (int j = 1; j <= tot; ++j) {
                int tmp = i * prime[j];
                if (tmp > m) break;
                f[tmp] = true;
                if (i % prime[j] == 0) break;
            }
        }        
    }
    inline int sub(int x , int y) {
        x -= y;
        while (x < 0) x += P;
        return x;
    }
    inline void multipy(Tmatrix &a , Tmatrix b) {
        Tmatrix c;
        for (int i = 0; i < p; ++i) {
            for (int j = 0; j < p; ++j) {
                c.mat[i][j] = 0;
            }
        }
        for (int i = 0; i < p; ++i) {
            for (int j = 0; j < p; ++j) {
                for (int k = 0; k < p; ++k) {
                    c.mat[i][j] = (c.mat[i][j] + 1ll * a.mat[i][k] * b.mat[k][j] % P) % P;
                }
            }
        }
        for (int i = 0; i < p; ++i) {
            for (int j = 0; j < p; ++j) {
                a.mat[i][j] = c.mat[i][j];
            }
        }
    }
    inline void qpow(Tmatrix &a , int n) {
        Tmatrix b , res;
        for (int i = 0; i < p; ++i) {
            for (int j = 0; j < p; ++j) {
                res.mat[i][j] = (i == j);
                b.mat[i][j] = a.mat[i][j];
            }
        }
        while (n > 0) {
            if (n & 1) multipy(res , b);
            multipy(b , b);
            n >>= 1;
        }
        for (int i = 0; i < p; ++i) {
            for (int j = 0; j < p; ++j) {
                a.mat[i][j] = res.mat[i][j];
            }
        }
    }
    inline int calc(int n , int type) {
        for (int i = 0; i < p; ++i) {
            for (int j = 0; j < p; ++j) {
                int k = (i - j + p) % p;
                a.mat[i][j] = type == 0 ? sa[k] : sb[k];
            } 
        }    
        qpow(a , n);
        return a.mat[0][0];
    }
    
    int main() {
        
        read(n); read(m); read(p);
        sieve( );
        for (int i = 1; i <= m; ++i) {
            sa[i % p] = (sa[i % p] + 1) % P;
            if (!lab[i]) sb[i % p] = (sb[i % p] + 1) % P;    
        }
        printf("%d
    " , sub(calc(n , 0) , calc(n , 1)));
        
        return 0;
    }
  • 相关阅读:
    杭州办理招行香港一卡通(两地一卡通)攻略
    Android高手进阶教程(二十)之Android与JavaScript方法相互调用!
    Android应用的自动升级、更新模块的实现
    18个最好的jQuery表格插件
    系统的本地策略不允许你采用交互式登录
    android中判断横屏或者竖屏并改变背景
    记录几个东东
    jsAnim学习
    win7下安装oracle10g出现未知错误,程序异常终止
    oracle创建用户并授权
  • 原文地址:https://www.cnblogs.com/evenbao/p/10928102.html
Copyright © 2011-2022 走看看