Xor-sequences CodeForces - 691E || 矩阵快速幂
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 ;
}
Xor-sequences CodeForces - 691E || 矩阵快速幂的更多相关文章
- codeforces 691E 矩阵快速幂+dp
传送门:https://codeforces.com/contest/691/problem/E 题意:给定长度为n的序列,从序列中选择k个数(可以重复选择),使得得到的排列满足xi与xi+1异或的二 ...
- Codeforces 691E题解 DP+矩阵快速幂
题面 传送门:http://codeforces.com/problemset/problem/691/E E. Xor-sequences time limit per test3 seconds ...
- Codeforces Round #257 (Div. 2) B. Jzzhu and Sequences (矩阵快速幂)
题目链接:http://codeforces.com/problemset/problem/450/B 题意很好懂,矩阵快速幂模版题. /* | 1, -1 | | fn | | 1, 0 | | f ...
- Codeforces 450B div.2 Jzzhu and Sequences 矩阵快速幂or规律
Jzzhu has invented a kind of sequences, they meet the following property: You are given x and y, ple ...
- CodeForces - 691E Xor-sequences 【矩阵快速幂】
题目链接 http://codeforces.com/problemset/problem/691/E 题意 给出一个长度为n的序列,从其中选择k个数 组成长度为k的序列,因为(k 有可能 > ...
- codeforces 450B B. Jzzhu and Sequences(矩阵快速幂)
题目链接: B. Jzzhu and Sequences time limit per test 1 second memory limit per test 256 megabytes input ...
- codeforces 691E Xor-sequences 矩阵快速幂
思路:刚开始 n个元素,a[i][j]代表以i开头,j结尾的二元组符合条件的有多少 这是等于长度为2的数量 长度为3的数量为a*a,所以长度为n的数量是a^(k-1) 然后就是矩阵快速幂,然而我并不能 ...
- CodeForces 450B Jzzhu and Sequences(矩阵快速幂)题解
思路: 之前那篇完全没想清楚,给删了,下午一上班突然想明白了. 讲一下这道题的大概思路,应该就明白矩阵快速幂是怎么回事了. 我们首先可以推导出 学过矩阵的都应该看得懂,我们把它简写成T*A(n-1)= ...
- Codeforces 691E Xor-sequences(矩阵快速幂)
You are given n integers a1, a2, ..., an. A sequence of integers x1, x2, ..., xk is called a & ...
随机推荐
- tomcat重启报错
一.tomcat重启报java环境变量错 报错信息详细如下: Neither the JAVA_HOME nor the JRE_HOME environment variable is define ...
- redis中键值对中值的各种类型
1 value的最基本的数据类型是String 2 如果value是一张图片 先对图片进行base64编码成一个字符串,然后再保存到redis中,用的时候进行base64解码即可. 这是base64的 ...
- PPAPI与Browser间使用AsyncIPC通信
採用AsyncIpc这个项目(https://github.com/hicdre/AsyncIpc).来完毕PPAPI Plugin进程与Browser进程的通信. foruok原创.如需转载请关注f ...
- JAVA 0 的突破
使用IntelliJ Idea 开发的一个Java 处理数据文件折行的问题,整体来说功能比较简单的一个java脚本的开发,跨平台的优势可以处理windows和lunix平台的文件折行 package ...
- ruby require
require一般用来加载其它的类,如: #Ruby代码 : require 'dbi' require "rexml/document" 但是上面加载的是标准类库里面的文 ...
- sdut oj 1510 Contest02-4 Spiral
Contest02-4 Spiral Time Limit: 1000ms Memory limit: 65536K 有疑问?点这里^_^ 题目描述 Given an odd number n, ...
- linux初级学习笔记五:bash特性详解!(视频序号:03_2,3)
本节学习的命令:history,alias,ualias,\CMD 本节学习的技能: bash的特性 光标跳转 查看命令历史 命令历史的使用技巧 给命令起别名 命令替换 文件名通配符 shell: ...
- hdu 2066 一个人的旅行 解题报告
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2066 题目意思:给出T条路,和草儿家相邻的城市编号,以及草儿想去的地方的编号.问从草儿家到达草儿想去的 ...
- POJ - 1236 Network of Schools(有向图的强连通分量)
d.各学校之间有单向的网络,每个学校得到一套软件后,可以通过单向网络向周边的学校传输, 问题1:初始至少需要向多少个学校发放软件,使得网络内所有的学校最终都能得到软件. 问题2:至少需要添加几条传输线 ...
- Oracle中如何用SQL检测字段是否包括中文字符
用Oracle的编码转换的函数Convert实现,测试后可行. SQL> select * 2 from (select 'abcd' c1 from dual 3 ...