CF691E Xor-sequences

可以用矩阵快速幂解决

由于k很多,但是我们分析可以看出,dp[k]=dp[k-1] * a(dp[k]和a都是矩阵)

(a[i][j]即a[i]^a[j]中二进制1的格式模3是否等于0)

dp[1]是什么自己想一想

最后求dp[k]的元素之和即可

#include <cstdio>
#include <iostream>
#include <cstring>
#define MOD 1000000007
#define MAXN 105
using namespace std;
long long n,k,ans;
//快读快写
inline long long read(){
	char ch;
	long long f=1,x=0;
	ch=getchar();
	while (ch>'9'||ch<'0'){
		if (ch=='-'){
			f=-1;
		}
		ch=getchar();
	}
	while (ch<='9'&&ch>='0'){
		x=x*10+ch-'0';
		ch=getchar();
	}
	return f*x;
}
inline void print(long long x){
	if (x<0) x=-x,putchar('-');
	if (x>9) print(x/10);
	putchar(x%10+'0');
}

struct binary{
	bool num[65];
	long long len;
	void clear(){
		memset(num,0,sizeof(num));
	}
	void convert(long long a){
		long long i=0;
		while (a>0){
			num[i++]=a&1;
			a>>=1;
		}
		len=i;
	}
	long long SumTrue(){
		long long sum=0;
		for (long long j=0;j<len;j++){
			sum+=num[j];
		}
		return sum;
	}
}a[MAXN];
binary operator ^ (const binary &a,const binary &b){
	binary c;
	long long maxlen=max(a.len,b.len);
	for (long long i=0;i<maxlen;i++){
		c.num[i]=a.num[i] xor b.num[i];
	}
	c.len=maxlen;
	return c;
}

struct matrix{
	long long v[MAXN][MAXN];
	void clear(){
		memset(v,0,sizeof(v));
	}
	void YPYlovesDYF(){
		for (long long i=0;i<n;i++){
			for (long long j=0;j<n;j++){
			    binary c=a[i]^a[j];
			    v[i][j]=(c.SumTrue()%3==0);
			}
		}
	}
};
matrix operator *(const matrix &a,const matrix &b){
	matrix ans;
	ans.clear();
	for (long long i=0;i<n;i++){
		for (long long j=0;j<n;j++){
			for (long long k=0;k<n;k++){
				ans.v[i][j]=(ans.v[i][j]+a.v[i][k]*b.v[k][j])%MOD;
			}
		}
	}
	return ans;
}

//矩阵快速幂
matrix ksm(matrix a,long long pows){
	matrix ans;
	ans.clear();
	for (long long i=0;i<n;i++){
	    ans.v[i][i]=1;
	}
	while (pows>0){
		if (pows&1){
			ans=ans*a;
		}
		a=a*a;
		pows>>=1;
	}
	return ans;
}
int main(){
	n=read();
	k=read();
	long long temp;
	for (long long i=0;i<n;i++){
		temp=read();
		a[i].clear();
		a[i].convert(temp);
	}
	matrix ans;
	ans.YPYlovesDYF();
	ans=ksm(ans,k-1);
	long long ret=0;
	for (long long i=0;i<n;i++){
	    for (long long j=0;j<n;j++){
	        ret=(ret+ans.v[i][j])%MOD;
	    }
	}
	print(ret);
	return 0;
}

发现自己太弱了,其实不用模拟二进制,用位运算来计算1的个数也可以

int count(ll a)
{
    int ans = 0;
    while(a){
        if(a & 1) ans++;
        a >>= 1;
    }
    return ans;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值