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 || 矩阵快速幂的更多相关文章

  1. codeforces 691E 矩阵快速幂+dp

    传送门:https://codeforces.com/contest/691/problem/E 题意:给定长度为n的序列,从序列中选择k个数(可以重复选择),使得得到的排列满足xi与xi+1异或的二 ...

  2. Codeforces 691E题解 DP+矩阵快速幂

    题面 传送门:http://codeforces.com/problemset/problem/691/E E. Xor-sequences time limit per test3 seconds ...

  3. Codeforces Round #257 (Div. 2) B. Jzzhu and Sequences (矩阵快速幂)

    题目链接:http://codeforces.com/problemset/problem/450/B 题意很好懂,矩阵快速幂模版题. /* | 1, -1 | | fn | | 1, 0 | | f ...

  4. 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 ...

  5. CodeForces - 691E Xor-sequences 【矩阵快速幂】

    题目链接 http://codeforces.com/problemset/problem/691/E 题意 给出一个长度为n的序列,从其中选择k个数 组成长度为k的序列,因为(k 有可能 > ...

  6. codeforces 450B B. Jzzhu and Sequences(矩阵快速幂)

    题目链接: B. Jzzhu and Sequences time limit per test 1 second memory limit per test 256 megabytes input ...

  7. codeforces 691E Xor-sequences 矩阵快速幂

    思路:刚开始 n个元素,a[i][j]代表以i开头,j结尾的二元组符合条件的有多少 这是等于长度为2的数量 长度为3的数量为a*a,所以长度为n的数量是a^(k-1) 然后就是矩阵快速幂,然而我并不能 ...

  8. CodeForces 450B Jzzhu and Sequences(矩阵快速幂)题解

    思路: 之前那篇完全没想清楚,给删了,下午一上班突然想明白了. 讲一下这道题的大概思路,应该就明白矩阵快速幂是怎么回事了. 我们首先可以推导出 学过矩阵的都应该看得懂,我们把它简写成T*A(n-1)= ...

  9. Codeforces 691E Xor-sequences(矩阵快速幂)

    You are given n integers a1,  a2,  ...,  an. A sequence of integers x1,  x2,  ...,  xk is called a & ...

随机推荐

  1. java语句顺序有时非常重要

    我们学习java时,通常被告知,变量定义的顺序不重要,可是下面程序确在jdk 1.7上执行出错. public class FactoryImpl implements Serializable { ...

  2. VC最小化到托盘程序

    在实际操作电脑的过程中,我们常常可以看到一些应用程序可以最小化到桌面右下角的托盘中显示,如一些杀毒软件等开机就显示在托盘中,或是我们常用的QQ等聊天工具,都可以最小化在托盘中,如图-1. 在图-1中, ...

  3. hive impala C++ Java垃圾回收 Garbage Collection GC

    hive impala impala  推荐每个节点内存  2^7~2^8GB Impala与Hive的比较 - 文章 - 伯乐在线 http://blog.jobbole.com/43233/ &l ...

  4. 该项目不在c:\ 请确认该项目的位置

    该项目不在c:\ 请确认该项目的位置 - CSDN博客https://blog.csdn.net/feilong1lantern/article/details/50388414 在删除不掉的文件夹目 ...

  5. 获取Android设备无线和以太网MAC地址

    package com.raycloud.wolf.blogformac; import android.net.wifi.WifiManager; import android.support.v7 ...

  6. 最短路Dijkstra算法的一些扩展问题

    最短路Dijkstra算法的一些扩展问题     很早以前写过关于A*求k短路的文章,那时候还不明白为什么还可以把所有点重复的放入堆中,只知道那样求出来的就是对的.知其然不知其所以然是件容易引发伤痛的 ...

  7. AutoEventWireup

    Page_PreInit & OnPreInit - whats the difference? https://forums.asp.net/t/1095903.aspx?Page_PreI ...

  8. java 连接飞信API

    通过java连接飞信api给自己的好友(包括自己)发送飞信内容.如果对方的手机号非你的飞信好友则不能发送.​​1. [代码]飞信发送类     package per.artisan.fetion; ...

  9. BZOJ1040:骑士(基环树DP)

    Z国的骑士团是一个很有势力的组织,帮会中汇聚了来自各地的精英.他们劫富济贫,惩恶扬善,受到社会各界的赞扬.最近发生了一件可怕的事情,邪恶的Y国发动了一场针对Z国的侵略战争.战火绵延五百里,在和平环境中 ...

  10. C++标准编程:虚函数与内联

    我们曾经在讨论C++的时候,经常会问到:“虚函数能被声明为内联吗?”现在,我们几乎听不到这个问题了.现在听到的是:“你不应该使print成为内联的.声明一个虚函数为内联是错误的!” 这种说法的两个主要 ...