zoukankan      html  css  js  c++  java
  • codeforces 691E 矩阵快速幂+dp

    传送门:https://codeforces.com/contest/691/problem/E

    题意:给定长度为n的序列,从序列中选择k个数(可以重复选择),使得得到的排列满足xi与xi+1异或的二进制中1的个数是3的倍数。问长度为k的满足条件的序列有多少种?

    题解:dp状态定义为,在前i个数中以aj为结尾的方案数量

    则转移为

    因为是求和的转移,可以用矩阵快速幂将O(n)的求和加速为log级别

    接下来的问题就是然后填系数了,因为要累加,所以只要时,我们将矩阵的第i行第j列的系数填为1即可

    目的:

    由于也是一个求和的转移,所以实际上我们将所得到的系数矩阵求一个k次幂即可得到答案

    总复杂度为矩阵乘法的复杂度*矩阵快速幂的复杂度 O(n^3*log2n)

    代码:

    /**
     *        ┏┓    ┏┓
     *        ┏┛┗━━━━━━━┛┗━━━┓
     *        ┃       ┃  
     *        ┃   ━    ┃
     *        ┃ >   < ┃
     *        ┃       ┃
     *        ┃... ⌒ ...  ┃
     *        ┃       ┃
     *        ┗━┓   ┏━┛
     *          ┃   ┃ Code is far away from bug with the animal protecting          
     *          ┃   ┃   神兽保佑,代码无bug
     *          ┃   ┃           
     *          ┃   ┃        
     *          ┃   ┃
     *          ┃   ┃           
     *          ┃   ┗━━━┓
     *          ┃       ┣┓
     *          ┃       ┏┛
     *          ┗┓┓┏━┳┓┏┛
     *           ┃┫┫ ┃┫┫
     *           ┗┻┛ ┗┻┛
     */
    // warm heart, wagging tail,and a smile just for you!
    //                                                                     ███████████
    //                                                                   ███╬╬╬╬╬╬╬╬╬╬███
    //                                                                ███╬╬╬╬╬████╬╬╬╬╬╬███
    //                                            ███████████       ██╬╬╬╬╬████╬╬████╬╬╬╬╬██
    //                                      █████████╬╬╬╬╬████████████╬╬╬╬╬██╬╬╬╬╬╬███╬╬╬╬╬██
    //                               ████████╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬█████████╬╬╬╬╬╬██╬╬╬╬╬╬╬██
    //                             ████╬██╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬█████████╬╬╬╬╬╬╬╬╬╬╬██
    //                           ███╬╬╬█╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬██╬╬███╬╬╬╬╬╬╬█████
    //                         ███╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬██╬╬╬████████╬╬╬╬╬██
    //                       ███╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬███╬╬╬╬╬╬╬╬╬███
    //                     ███╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬█████╬╬╬╬╬╬╬██
    //                 ████╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬████╬╬╬╬╬████
    //     █████████████╬╬╬╬╬╬╬╬██╬╬╬╬╬████╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬█████╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬███╬╬╬╬██████
    //   ████╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬██╬╬██████╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬██████╬╬╬╬╬╬╬███████████╬╬╬╬╬╬╬╬██╬╬╬██╬╬╬██
    // ███╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬██╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬██╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬████╬╬╬╬╬╬╬╬╬╬╬█╬╬╬╬╬╬╬██╬╬╬╬╬╬╬╬██
    // ██╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬██╬╬╬╬▓▓▓▓▓▓╬╬╬████╬╬████╬╬╬╬╬╬╬▓▓▓▓▓▓▓▓██╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬██╬╬╬╬╬╬╬███
    // ██╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬██████▓▓▓▓▓▓▓╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬▓▓▓▓▓▓▓██╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬██╬╬╬╬█████
    // ███╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬███╬╬╬╬╬██╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬█████╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬████████
    //   ███╬╬╬╬╬╬╬╬╬╬╬╬╬█████╬╬╬╬╬╬╬╬██╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬███╬╬██╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬██
    //       ██████████████  ████╬╬╬╬╬╬███████████████████████████╬╬╬╬╬██╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬████
    //                         ███████                           █████  ███████████████████
    #include <set>
    #include <map>
    #include <deque>
    #include <queue>
    #include <stack>
    #include <cmath>
    #include <ctime>
    #include <bitset>
    #include <cstdio>
    #include <string>
    #include <vector>
    #include <cstdlib>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    
    typedef long long LL;
    typedef pair<LL, LL> pLL;
    typedef pair<LL, int> pLi;
    typedef pair<int, LL> pil;;
    typedef pair<int, int> pii;
    typedef unsigned long long uLL;
    #define lson l,mid,rt<<1
    #define rson mid+1,r,rt<<1|1
    #define bug printf("*********
    ")
    #define FIN freopen("input.txt","r",stdin);
    #define FON freopen("output.txt","w+",stdout);
    #define IO ios::sync_with_stdio(false),cin.tie(0)
    #define debug1(x) cout<<"["<<#x<<" "<<(x)<<"]
    "
    #define debug2(x,y) cout<<"["<<#x<<" "<<(x)<<" "<<#y<<" "<<(y)<<"]
    "
    #define debug3(x,y,z) cout<<"["<<#x<<" "<<(x)<<" "<<#y<<" "<<(y)<<" "<<#z<<" "<<z<<"]
    "
    LL read() {
        int x = 0, f = 1; char ch = getchar();
        while(ch < '0' || ch > '9') {
            if(ch == '-')f = -1;
            ch = getchar();
        }
        while(ch >= '0' && ch <= '9') {
            x = x * 10 + ch - '0';
            ch = getchar();
        }
        return x * f;
    }
    const double eps = 1e-8;
    const int mod = 1e9 + 7;
    const int maxn = 3e5 + 5;
    const int INF = 0x3f3f3f3f;
    const LL INFLL = 0x3f3f3f3f3f3f3f3f;
    // 给定长度为n的序列,从序列中选择k个数(可以重复选择),
    // 使得得到的排列满足xi与xi+1异或的二进制中1的个数是3的倍数。
    // 问长度为k的满足条件的序列有多少种?
    LL a[maxn];
    LL dp[105][105];
    struct matrix {//矩阵
        int n;//
        int m;//
        long long a[105][105];
        matrix() {//构造函数
            n = 2;
            m = 2;
            memset(a, 0, sizeof(a));
        }
        matrix(int x, int y) {
            n = x;
            m = y;
            memset(a, 0, sizeof(a));
        }
        void print() {
            for(int i = 1; i <= n; i++) {
                for(int j = 1; j <= m; j++) {
                    printf("%d ", a[i][j]);
                }
                printf("
    ");
            }
        }
        void setv(int x) {//初始化
            if(x == 0) {
                memset(a, 0, sizeof(a));
            }
            if(x == 1) {
                memset(a, 0, sizeof(a));
                for(int i = 1; i <= n; i++) a[i][i] = 1;
            }
        }
        friend matrix operator *(matrix x, matrix y) { //矩阵乘法
            matrix tmp = matrix(x.n, y.m);
            for(int i = 1; i <= x.n; i++) {
                for(int j = 1; j <= y.m; j++) {
                    tmp.a[i][j] = 0;
                    for(int k = 1; k <= y.n; k++) {
                        tmp.a[i][j] += (x.a[i][k] * y.a[k][j]) % mod;
                    }
                    tmp.a[i][j] %= mod;
                }
            }
            return tmp;
        }
    };
    int n;
    LL  k;
    matrix fast_pow(matrix x, long long k) { //矩阵快速幂
        matrix ans = matrix(n, n);
        ans.setv(1);//初始化为1
        while(k > 0) { //类似整数快速幂
            if(k & 1) {
                ans = ans * x;
            }
            k >>= 1;
            x = x * x;
        }
        return ans;
    }
    
    int cal(LL x) {
        int cnt = 0;
        while(x) {
            if(x & 1 ) {
                cnt++;
            }
            x /= 2;
        }
        return cnt;
    }
    int main() {
    #ifndef ONLINE_JUDGE
        FIN
    #endif
        scanf("%d%lld", &n, &k);
        for(int i = 1; i <= n; i++) {
            scanf("%lld", &a[i]);
        }
        matrix xor_mat = matrix(n, n);
        for(int i = 1; i <= n; i++) {
            for(int j = 1; j <= n; j++) {
                if(cal(a[i]^a[j]) % 3 == 0 )    xor_mat.a[i][j] = 1;
                else xor_mat.a[i][j] = 0;
            }
        }
        xor_mat = fast_pow(xor_mat, k - 1);
        LL ans = 0;
        for(int i = 1; i <= n; i++) {
            for(int j = 1; j <= n; j++) {
                ans += xor_mat.a[i][j];
            }
            ans %= mod;
        }
        cout << ans << endl;
        return 0;
    }
    View Code
    每一个不曾刷题的日子 都是对生命的辜负 从弱小到强大,需要一段时间的沉淀,就是现在了 ~buerdepepeqi
  • 相关阅读:
    2003开机自动登陆然后马上锁定计算机
    修改DNS、网关的VBS代码,不需重起即时生效
    页面自动刷新代码
    dos命令给权限
    无法运行VBS代码
    去掉2003或2kserver版的系统启动报错
    让易语言的信息框总在最前
    教你轻松搞定RJ45网线接头
    小技巧:如何设定永久通用WinRAR压缩密码
    Bootstrap入门教程
  • 原文地址:https://www.cnblogs.com/buerdepepeqi/p/10662836.html
Copyright © 2011-2022 走看看