codeforces 691E 矩阵快速幂+dp
传送门:https://codeforces.com/contest/691/problem/E
题意:给定长度为n的序列,从序列中选择k个数(可以重复选择),使得得到的排列满足xi与xi+1异或的二进制中1的个数是3的倍数。问长度为k的满足条件的序列有多少种?
题解:dp状态定义为,在前i个数中以aj为结尾的方案数量
则转移为
因为是求和的转移,可以用矩阵快速幂将O(n)的求和加速为log级别
接下来的问题就是然后填系数了,因为要累加,所以只要时,我们将矩阵的第i行第j列的系数填为1即可
目的:
由于也是一个求和的转移,所以实际上我们将所得到的系数矩阵求一个k次幂即可得到答案
总复杂度为矩阵乘法的复杂度*矩阵快速幂的复杂度 O(n^3*log2n)
代码:
- /**
- * ┏┓ ┏┓
- * ┏┛┗━━━━━━━┛┗━━━┓
- * ┃ ┃
- * ┃ ━ ┃
- * ┃ > < ┃
- * ┃ ┃
- * ┃... ⌒ ... ┃
- * ┃ ┃
- * ┗━┓ ┏━┛
- * ┃ ┃ Code is far away from bug with the animal protecting
- * ┃ ┃ 神兽保佑,代码无bug
- * ┃ ┃
- * ┃ ┃
- * ┃ ┃
- * ┃ ┃
- * ┃ ┗━━━┓
- * ┃ ┣┓
- * ┃ ┏┛
- * ┗┓┓┏━┳┓┏┛
- * ┃┫┫ ┃┫┫
- * ┗┻┛ ┗┻┛
- */
- // warm heart, wagging tail,and a smile just for you!
- // ███████████
- // ███╬╬╬╬╬╬╬╬╬╬███
- // ███╬╬╬╬╬████╬╬╬╬╬╬███
- // ███████████ ██╬╬╬╬╬████╬╬████╬╬╬╬╬██
- // █████████╬╬╬╬╬████████████╬╬╬╬╬██╬╬╬╬╬╬███╬╬╬╬╬██
- // ████████╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬█████████╬╬╬╬╬╬██╬╬╬╬╬╬╬██
- // ████╬██╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬█████████╬╬╬╬╬╬╬╬╬╬╬██
- // ███╬╬╬█╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬██╬╬███╬╬╬╬╬╬╬█████
- // ███╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬██╬╬╬████████╬╬╬╬╬██
- // ███╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬███╬╬╬╬╬╬╬╬╬███
- // ███╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬█████╬╬╬╬╬╬╬██
- // ████╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬████╬╬╬╬╬████
- // █████████████╬╬╬╬╬╬╬╬██╬╬╬╬╬████╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬█████╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬███╬╬╬╬██████
- // ████╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬██╬╬██████╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬██████╬╬╬╬╬╬╬███████████╬╬╬╬╬╬╬╬██╬╬╬██╬╬╬██
- // ███╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬██╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬██╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬████╬╬╬╬╬╬╬╬╬╬╬█╬╬╬╬╬╬╬██╬╬╬╬╬╬╬╬██
- // ██╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬██╬╬╬╬▓▓▓▓▓▓╬╬╬████╬╬████╬╬╬╬╬╬╬▓▓▓▓▓▓▓▓██╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬██╬╬╬╬╬╬╬███
- // ██╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬██████▓▓▓▓▓▓▓╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬▓▓▓▓▓▓▓██╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬██╬╬╬╬█████
- // ███╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬███╬╬╬╬╬██╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬█████╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬████████
- // ███╬╬╬╬╬╬╬╬╬╬╬╬╬█████╬╬╬╬╬╬╬╬██╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬███╬╬██╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬██
- // ██████████████ ████╬╬╬╬╬╬███████████████████████████╬╬╬╬╬██╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬████
- // ███████ █████ ███████████████████
- #include <set>
- #include <map>
- #include <deque>
- #include <queue>
- #include <stack>
- #include <cmath>
- #include <ctime>
- #include <bitset>
- #include <cstdio>
- #include <string>
- #include <vector>
- #include <cstdlib>
- #include <cstring>
- #include <iostream>
- #include <algorithm>
- using namespace std;
- typedef long long LL;
- typedef pair<LL, LL> pLL;
- typedef pair<LL, int> pLi;
- typedef pair<int, LL> pil;;
- typedef pair<int, int> pii;
- typedef unsigned long long uLL;
- #define lson l,mid,rt<<1
- #define rson mid+1,r,rt<<1|1
- #define bug printf("*********\n")
- #define FIN freopen("input.txt","r",stdin);
- #define FON freopen("output.txt","w+",stdout);
- #define IO ios::sync_with_stdio(false),cin.tie(0)
- #define debug1(x) cout<<"["<<#x<<" "<<(x)<<"]\n"
- #define debug2(x,y) cout<<"["<<#x<<" "<<(x)<<" "<<#y<<" "<<(y)<<"]\n"
- #define debug3(x,y,z) cout<<"["<<#x<<" "<<(x)<<" "<<#y<<" "<<(y)<<" "<<#z<<" "<<z<<"]\n"
- LL read() {
- int x = , f = ; char ch = getchar();
- while(ch < '' || ch > '') {
- if(ch == '-')f = -;
- ch = getchar();
- }
- while(ch >= '' && ch <= '') {
- x = x * + ch - '';
- ch = getchar();
- }
- return x * f;
- }
- const double eps = 1e-;
- const int mod = 1e9 + ;
- const int maxn = 3e5 + ;
- const int INF = 0x3f3f3f3f;
- const LL INFLL = 0x3f3f3f3f3f3f3f3f;
- // 给定长度为n的序列,从序列中选择k个数(可以重复选择),
- // 使得得到的排列满足xi与xi+1异或的二进制中1的个数是3的倍数。
- // 问长度为k的满足条件的序列有多少种?
- LL a[maxn];
- LL dp[][];
- struct matrix {//矩阵
- int n;//长
- int m;//宽
- long long a[][];
- matrix() {//构造函数
- n = ;
- m = ;
- memset(a, , sizeof(a));
- }
- matrix(int x, int y) {
- n = x;
- m = y;
- memset(a, , sizeof(a));
- }
- void print() {
- for(int i = ; i <= n; i++) {
- for(int j = ; j <= m; j++) {
- printf("%d ", a[i][j]);
- }
- printf("\n");
- }
- }
- void setv(int x) {//初始化
- if(x == ) {
- memset(a, , sizeof(a));
- }
- if(x == ) {
- memset(a, , sizeof(a));
- for(int i = ; i <= n; i++) a[i][i] = ;
- }
- }
- friend matrix operator *(matrix x, matrix y) { //矩阵乘法
- matrix tmp = matrix(x.n, y.m);
- for(int i = ; i <= x.n; i++) {
- for(int j = ; j <= y.m; j++) {
- tmp.a[i][j] = ;
- for(int k = ; k <= y.n; k++) {
- tmp.a[i][j] += (x.a[i][k] * y.a[k][j]) % mod;
- }
- tmp.a[i][j] %= mod;
- }
- }
- return tmp;
- }
- };
- int n;
- LL k;
- matrix fast_pow(matrix x, long long k) { //矩阵快速幂
- matrix ans = matrix(n, n);
- ans.setv();//初始化为1
- while(k > ) { //类似整数快速幂
- if(k & ) {
- ans = ans * x;
- }
- k >>= ;
- x = x * x;
- }
- return ans;
- }
- int cal(LL x) {
- int cnt = ;
- while(x) {
- if(x & ) {
- cnt++;
- }
- x /= ;
- }
- return cnt;
- }
- int main() {
- #ifndef ONLINE_JUDGE
- FIN
- #endif
- scanf("%d%lld", &n, &k);
- for(int i = ; i <= n; i++) {
- scanf("%lld", &a[i]);
- }
- matrix xor_mat = matrix(n, n);
- for(int i = ; i <= n; i++) {
- for(int j = ; j <= n; j++) {
- if(cal(a[i]^a[j]) % == ) xor_mat.a[i][j] = ;
- else xor_mat.a[i][j] = ;
- }
- }
- xor_mat = fast_pow(xor_mat, k - );
- LL ans = ;
- for(int i = ; i <= n; i++) {
- for(int j = ; j <= n; j++) {
- ans += xor_mat.a[i][j];
- }
- ans %= mod;
- }
- cout << ans << endl;
- return ;
- }
codeforces 691E 矩阵快速幂+dp的更多相关文章
- Xor-sequences CodeForces - 691E || 矩阵快速幂
Xor-sequences CodeForces - 691E 题意:在有n个数的数列中选k个数(可以重复选,可以不按顺序)形成一个数列,使得任意相邻两个数异或的结果转换成二进制后其中1的个数是三的倍 ...
- Codeforces 576D Flights for Regular Customers 矩阵快速幂+DP
题意: 给一个$n$点$m$边的连通图 每个边有一个权值$d$ 当且仅当当前走过的步数$\ge d$时 才可以走这条边 问从节点$1$到节点$n$的最短路 好神的一道题 直接写做法喽 首先我们对边按$ ...
- Codeforces 954 dijsktra 离散化矩阵快速幂DP 前缀和二分check
A B C D 给你一个联通图 给定S,T 要求你加一条边使得ST的最短距离不会减少 问你有多少种方法 因为N<=1000 所以N^2枚举边数 迪杰斯特拉两次 求出Sdis 和 Tdis 如果d ...
- P1357 花园 (矩阵快速幂+ DP)
题意:一个只含字母C和P的环形串 求长度为n且每m个连续字符不含有超过k个C的方案数 m <= 5 n <= 1e15 题解:用一个m位二进制表示状态 转移很好想 但是这个题是用矩阵快速 ...
- BZOJ1009 矩阵快速幂+DP+KMP
Problem 1009. -- [HNOI2008]GT考试 1009: [HNOI2008]GT考试 Time Limit: 1 Sec Memory Limit: 162 MBSubmit: ...
- COJ 1208 矩阵快速幂DP
题目大意: f(i) 是一个斐波那契数列 , 求sum(f(i)^k)的总和 由于n极大,所以考虑矩阵快速幂加速 我们要求解最后的sum[n] 首先我们需要思考 sum[n] = sum[n-1] + ...
- Codeforces 989E A Trance of Nightfall 矩阵快速幂+DP
题意:二维平面上右一点集$S$,共$n$个元素,开始位于平面上任意点$P$,$P$不一定属于$S$,每次操作为选一条至少包含$S$中两个元素和当前位置$P$的直线,每条直线选取概率相同,同一直线上每个 ...
- BZOJ1009: [HNOI2008]GT考试 (矩阵快速幂 + DP)
题意:求一个长度为n的数字字符串 (n <= 1e9) 不出现子串s的方案数 题解:用f i,j表示长度为i匹配到在子串j的答案 用kmp的失配函数预处理一下 然后这个转移每一个都是一样的 所以 ...
- bzoj2004 矩阵快速幂优化状压dp
https://www.lydsy.com/JudgeOnline/problem.php?id=2004 以前只会状压dp和矩阵快速幂dp,没想到一道题还能组合起来一起用,算法竞赛真是奥妙重重 小Z ...
随机推荐
- 《算法图解》——第十章 K最近邻算法
第十章 K最近邻算法 1 K最近邻(k-nearest neighbours,KNN)——水果分类 2 创建推荐系统 利用相似的用户相距较近,但如何确定两位用户的相似程度呢? ①特征抽取 对水果 ...
- 生成dataset的几种方式
1.常用的方式通过sparksession读取外部文件或者数据生成dataset(这里就不讲了) 注: 生成Row对象的方法提一下:RowFactory.create(x,y,z),取Row中的数据 ...
- DevOps之六 shell以及pipeline 命令部署
一 使用shell命启动spring boot 项目 1. 使用shell停止当前项目 #!/bin/sh main() { clear pid=`ps -ef|grep xx.jar|grep -v ...
- Python坑系列:可变对象与不可变对象
在之前的文章 http://www.cnblogs.com/bitpeng/p/4748148.html 中,大家看到了ret.append(path) 和ret.append(path[:])的巨大 ...
- 如何使用HtmlTestRunner让自动化测试报告内容更丰富
原文出自:http://www.cnblogs.com/tsbc/p/4128150.html 简述 使用selenium webdriver + Python做自动化测试,执行完成后要生成测试报告, ...
- Scrum立会报告+燃尽图 05
此作业要求参见:[https://edu.cnblogs.com/campus/nenu/2018fall/homework/2195] 一.小组介绍 组长:王一可 组员:范靖旋,王硕,赵佳璐,范洪达 ...
- 对其中的一个特点将NABC的分析结果
一.题目要求 每一个组员针对其中的一个特点将NABC的分析结果发表博客上(截止日期4月8日晚24:00前). 二.分析结果 特点之一:通讯方便 <渴了么>这个安卓APP特点之一就是通讯方便 ...
- 浅谈Java变量的初始化顺序详解
规则1(无继承情况下):对于静态变量.静态初始化块.变量.初始化块.构造器,它们的初始化顺序依次是(静态变量.静态初始化块)>(变量.初始化块)>构造器证明代码: 复制代码 代码如下: p ...
- 周总结<3>
经过了一周的学习,我们在html以及C语言方面又有的新的知识点的学习,包括计算机导论也学会了路由器的设置. html 鼠标事件 C 二叉树的遍历代码 计算机导论 路由器的设置 Html案例: < ...
- ElasticSearch API 简要介绍
调用其API会返回很多信息,例如集群的信息,节点的信息等 检查集群的状态----Restful API说明 1:检查集群状态信息 2:管理集群 3:执行 增删改查 命令 4:执行高级命令 Restfu ...