Codeforces 691 E Xor-sequences 矩阵快速幂

题意

从n个数中挑选k个数做排列(是排列哦,如果两个数相同不判重),如果这k个数中,相邻的两个数异或的二进制结果中有3的倍数个1,这样的排列就是满足条件的。最后输出满足条件的排列的个数。

题解

处理出一个矩阵G,g[i][j] 表示num[i] 和 num[j] 异或满足条件
可知 G2 = G*G 中的 G2[i][j]就是以num[i]开头, num[j] 结尾,且k=3的满足条件的个数
G的n次方就是,Gn[i][j]就是以num[i]开头, num[j] 结尾,且k=n+1的满足条件的个数
用 矩阵快速幂 求出G(k-1)的所有元素和即为所求

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#define mod 1000000007
using namespace std;
typedef long long ll;
const ll MAX_N = 110LL;

ll n,k;
ll num[MAX_N];

struct graph
{
    ll a[MAX_N][MAX_N];
    friend graph operator * (graph &A, graph &B)
    {
        graph C;
        for(ll i=0;i<n;i++)
        {
            for(ll j=0;j<n;j++)
            {
                C.a[i][j] = (ll)0;
                for(ll k=0;k<n;k++)
                {
                    C.a[i][j] = (C.a[i][j] + (A.a[i][k]*B.a[k][j])%mod) % mod;
                }
            }
        }
        return C;
    }
    void init()
    {
        for(ll i=0;i<n;i++)
        {
            a[i][i] = 1;
            for(ll j=i+1;j<n;j++)
            {
                a[i][j] = a[j][i] = 0;
            }
        }
    }
    friend ostream& operator << (ostream &io, const graph &A)
    {
        for(ll i=0;i<n;i++)
        {
            for(ll j=0;j<n;j++)
            {
                io<<A.a[i][j]<<" ";
            }
            io<<endl;
        }
        return io;
    }
};

graph mod_pow(graph tg, ll kk)
{
    graph g;
    g.init();
    while(kk)
    {
        if(kk%2)
        {
            g = g*tg;
        }
        kk = kk>>1;
        tg = tg*tg;
    }
    return g;
}

int main()
{
    while(scanf("%I64d%I64d",&n,&k)!=EOF)
    {
        for(ll i=0;i<n;i++)
        {
            scanf("%I64d",&num[i]);
        }
        graph g2;
        for(ll i=0;i<n;i++)
        {
            g2.a[i][i] = 1LL;

            for(ll j=i+1;j<n;j++)
            {

                ll x = num[i]^num[j];
                ll cnt = 0LL;
                while(x)
                {
                    cnt += x&1;
                    x = x>>1;
                }
                if(cnt%3==0)
                {
                    g2.a[i][j] = g2.a[j][i] = 1;
                }
                else
                    g2.a[i][j] = g2.a[j][i] = 0;
            }
        }

        graph gk = mod_pow(g2, k-1);
        ll ans=0;
        for(ll i=0;i<n;i++)
        {
            for(ll j=0;j<n;j++)
            {
                ans = (ans+ gk.a[i][j])%mod;
            }
        }
        cout<<ans<<endl;
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值