Xor-sequences CodeForces - 691E

题意:在有n个数的数列中选k个数(可以重复选,可以不按顺序)形成一个数列,使得任意相邻两个数异或的结果转换成二进制后其中1的个数是三的倍数。求可能形成的不同数列个数(只要选出的数列中,任意两个元素在原序列中的位置不同,就算作不同的序列,比如在原数列[1,1]中选1个,那么第一个1和第二个1要分开算)。

方法:

很容易列出dp方程:

dp[k][i]表示取了k个,最后一个在第i位。a[i][j]表示i和j异或结果转换成二进制后1的个数是否是3的倍数,1表示是,0表示否。

$dp[k][i]=dp[k-1][1]*a[1][i]+...dp[k-1][n]*a[n][i]$

注意,不是$dp[k][i]=dp[k-1][1]*a[1][i]+...+dp[k-1][i-1]*a[i-1][i]$(这道题是可以重复、不按顺序选的,这么写就是不重复、按顺序)

那么,这样的算法复杂度就是O(nk),太慢了,需要优化。

从小数据开始:

n=3时:

dp[1][1]=1
dp[1][2]=1
dp[1][3]=1 dp[2][1]=dp[1][1]*a[1][1]+dp[1][2]*a[2][1]+dp[1][3]*a[3][1]
dp[2][2]=dp[1][1]*a[1][2]+dp[1][2]*a[2][2]+dp[1][3]*a[3][2]
dp[2][3]=dp[1][1]*a[1][3]+dp[1][2]*a[2][3]+dp[1][3]*a[3][3] dp[3][1]=dp[2][1]*a[1][1]+dp[2][2]*a[2][1]+dp[2][3]*a[3][1]
dp[3][2]=dp[2][1]*a[1][2]+dp[2][2]*a[2][2]+dp[2][3]*a[3][2]
dp[3][3]=dp[2][1]*a[1][3]+dp[2][2]*a[2][3]+dp[2][3]*a[3][3] 很容易可以发现:
矩阵1
dp[1][1] dp[1][2] dp[1][3]
矩阵2
a[1][1] a[1][2] a[1][3]
a[2][1] a[2][2] a[2][3]
a[3][1] a[3][2] a[3][3]
矩阵1*矩阵2
dp[2][1] dp[2][2] dp[2][3]

更大的数据以此类推,因此很容易想到用矩阵快速幂优化。

而要求dp[k][],就要由dp[1][]乘k-1次矩阵2,可以改为算出来矩阵2的k-1次幂放入矩阵3,再将dp[1][]乘上矩阵3,得到的就是dp[k][]。最终答案就是dp[k][1]+..+dp[k][n]。

所以说...这个矩阵快速幂的题..居然不用自己去构造转移矩阵??

另外:

__builtin_popcountll:参照__builtin_popcount,那个是针对long整型的,这个是针对long long的

还有手动写的

 #include<cstdio>
#include<cstring>
#define md 1000000007
typedef long long LL;
LL n,k,anss;
LL a[];
struct Mat
{
LL data[][],x,y;
Mat()
{
memset(data,,sizeof(data));
x=y=;
}
Mat operator*(const Mat& b)
{
Mat temp;
LL i,j,k;
for(i=;i<=x;i++)
for(j=;j<=b.y;j++)
for(k=;k<=y;k++)
temp.data[i][j]=(data[i][k]*b.data[k][j]+temp.data[i][j])%md;
temp.x=x;
temp.y=b.y;
return temp;
}
Mat& operator*=(const Mat& b)
{
return (*this)=(*this)*b;
}
Mat& operator=(const Mat& b)
{
memcpy(data,b.data,sizeof(data));
x=b.x;
y=b.y;
return *this;
}
}ma,o,bbb,ccc;
Mat pow(const Mat& a,LL b)
{
Mat ans=o;
if(b==) return ans;
Mat base=a;
while(b!=)
{
if(b&!=) ans*=base;
base*=base;
b>>=;
}
return ans;
}
int main()
{
LL i,j;
scanf("%I64d%I64d",&n,&k);
for(i=;i<=n;i++)
scanf("%I64d",&a[i]);
ma.x=ma.y=n;
for(i=;i<=n;i++)
for(j=;j<=n;j++)
ma.data[i][j]=(__builtin_popcountll(a[i]^a[j])%==);
o.x=o.y=n;
for(i=;i<=n;i++)
for(j=;j<=n;j++)
o.data[i][j]=(i==j);
bbb=pow(ma,k-);
ccc.x=;ccc.y=n;
for(i=;i<=n;i++)
ccc.data[][i]=;
ccc*=bbb;
for(i=;i<=n;i++)
anss=(anss+ccc.data[][i])%md;
printf("%I64d",anss);
return ;
}

最新文章

  1. 【C++】rand()函数,时间种子
  2. Hibernate笔记——hql总结
  3. jquery动态生成css样式表
  4. Debug Intro
  5. ZipArchive框架的文件压缩和解压
  6. win32进程间通讯--共享内存
  7. Web开发的绝美网站
  8. java.lang.Exception: Socket bind failed 服务器端口冲突--&gt;修改端口
  9. AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
  10. 生成excel文件
  11. NET基础课--XML基础
  12. hibernate.dialect是干嘛用的?
  13. 微信小程序下拉框
  14. 非vue-cli的花括号闪现问题
  15. 20172310 2017-2018-2 《程序设计与数据结构》实验三报告(敏捷开发与XP实践)
  16. springMVC 防重校验(拦截器)
  17. c++编程规范的纲要和记录 (转)
  18. Clear The Matrix CodeForces - 903F (状压)
  19. mysql 5.6.23的源码安装
  20. Monkey进行压力测试定位问题分析

热门文章

  1. ++*p,(*p)++,*p++与*++p四者的区别
  2. TC SRM 582 DIV 2
  3. js编程精解--笔记
  4. __sizeof__()
  5. Hive 特性及原理
  6. Mac JDK 多版本共存
  7. Bug不能重现的原因分析及其对策
  8. CentOS/Ubuntu安装GLIBCXX3.4.21
  9. 内部类 final变量的生命周期
  10. JS DOM1核心概要1