Xor-sequences CodeForces - 691E || 矩阵快速幂
2018-06-17 21:49:53来源:未知 阅读 ()
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的
还有手动写的
1 #include<cstdio> 2 #include<cstring> 3 #define md 1000000007 4 typedef long long LL; 5 LL n,k,anss; 6 LL a[101]; 7 struct Mat 8 { 9 LL data[101][101],x,y; 10 Mat() 11 { 12 memset(data,0,sizeof(data)); 13 x=y=0; 14 } 15 Mat operator*(const Mat& b) 16 { 17 Mat temp; 18 LL i,j,k; 19 for(i=1;i<=x;i++) 20 for(j=1;j<=b.y;j++) 21 for(k=1;k<=y;k++) 22 temp.data[i][j]=(data[i][k]*b.data[k][j]+temp.data[i][j])%md; 23 temp.x=x; 24 temp.y=b.y; 25 return temp; 26 } 27 Mat& operator*=(const Mat& b) 28 { 29 return (*this)=(*this)*b; 30 } 31 Mat& operator=(const Mat& b) 32 { 33 memcpy(data,b.data,sizeof(data)); 34 x=b.x; 35 y=b.y; 36 return *this; 37 } 38 }ma,o,bbb,ccc; 39 Mat pow(const Mat& a,LL b) 40 { 41 Mat ans=o; 42 if(b==0) return ans; 43 Mat base=a; 44 while(b!=0) 45 { 46 if(b&1!=0) ans*=base; 47 base*=base; 48 b>>=1; 49 } 50 return ans; 51 } 52 int main() 53 { 54 LL i,j; 55 scanf("%I64d%I64d",&n,&k); 56 for(i=1;i<=n;i++) 57 scanf("%I64d",&a[i]); 58 ma.x=ma.y=n; 59 for(i=1;i<=n;i++) 60 for(j=1;j<=n;j++) 61 ma.data[i][j]=(__builtin_popcountll(a[i]^a[j])%3==0); 62 o.x=o.y=n; 63 for(i=1;i<=n;i++) 64 for(j=1;j<=n;j++) 65 o.data[i][j]=(i==j); 66 bbb=pow(ma,k-1); 67 ccc.x=1;ccc.y=n; 68 for(i=1;i<=n;i++) 69 ccc.data[1][i]=1; 70 ccc*=bbb; 71 for(i=1;i<=n;i++) 72 anss=(anss+ccc.data[1][i])%md; 73 printf("%I64d",anss); 74 return 0; 75 }
标签:
版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有
- CodeForces 1326E - Bombs 2020-03-25
- CodeForces 1320D - Reachable Strings 2020-03-20
- CodeForces 1324 - Codeforces Round #627 (Div. 3) 2020-03-13
- CodeForces 710D Two Arithmetic Progressions 2020-03-06
- CodeForces 1313D Happy New Year 2020-03-04
IDC资讯: 主机资讯 注册资讯 托管资讯 vps资讯 网站建设
网站运营: 建站经验 策划盈利 搜索优化 网站推广 免费资源
网络编程: Asp.Net编程 Asp编程 Php编程 Xml编程 Access Mssql Mysql 其它
服务器技术: Web服务器 Ftp服务器 Mail服务器 Dns服务器 安全防护
软件技巧: 其它软件 Word Excel Powerpoint Ghost Vista QQ空间 QQ FlashGet 迅雷
网页制作: FrontPages Dreamweaver Javascript css photoshop fireworks Flash