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. leetcode -day17 Path Sum I II &amp; Flatten Binary Tree to Linked List &amp; Minimum Depth of Binary Tree

    1.  Path Sum Given a binary tree and a sum, determine if the tree has a root-to-leaf path such tha ...

  2. 在vs2005中添加lib库的方法

    方法一:在用到lib的地方加上  //强烈推荐这种方法.#pragma    comment(lib,"libname.lib") 方法二:     点击菜单命令 “项目/属性”, ...

  3. Python 003- 小知识汇总(更新中)

    #查询key是否存在,可以在使用未知的字典的时候使用 #-*- coding:utf-8 -*- D={'a':1,'c':3,'b':2} for key in sorted(D): print(k ...

  4. sanic官方文档解析之Response和Cookie

    1,Sanic的返回的响应体 使用Sanic中的response模块去创建响应对象 返回文本response.text文本(直接字符串就ok) 返回html文件,直接response.html文件(类 ...

  5. iOS中区分照片的来源

    原理就是通过枚举出每个assets group,然后取得group property,group property是个整数,对应头文件中的一些枚举值.用这个可以判断照片是从哪来的(相机胶卷.照片流.相 ...

  6. HDU3652 B-number —— 数位DP

    题目链接:https://vjudge.net/problem/HDU-3652 B-number Time Limit: 2000/1000 MS (Java/Others)    Memory L ...

  7. ios蓝牙开发(四)BabyBluetooth蓝牙库介绍

    BabyBluetooth 是一个最简单易用的蓝牙库,基于CoreBluetooth的封装,并兼容ios和mac osx. 特色: 基于原生CoreBluetooth框架封装的轻量级的开源库,可以帮你 ...

  8. poj 2771 Guardian of Decency 解题报告

    题目链接:http://poj.org/problem?id=2771 题目意思:有一个保守的老师要带他的学生来一次短途旅行,但是他又害怕有些人会变成情侣关系,于是就想出了一个方法: 1.身高差距   ...

  9. 「UVA524」 Prime Ring Problem 质数环

    Description 输入正整数n,把整数1,2,-,n组成一个环,使得相邻两个整数之和均为素数.输出时,从整数1开始逆时针排列.同一个环恰好输出一次.n<=16. A ring is com ...

  10. IOCP编程小结(中)

    上一篇主要谈了一些基本理念,本篇将谈谈我个人总结的一些IOCP编程技巧. 网络游戏前端服务器的需求和设计 首先介绍一下这个服务器的技术背景.在分布式网络游戏服务器中,前端连接服务器是一种很常见的设计. ...