首页 > 其他分享 >序列(dp+矩阵加速)

序列(dp+矩阵加速)

时间:2024-08-18 20:07:58浏览次数:5  
标签:输出 int res 矩阵 ..... 序列 dp

第2题     序列 查看测评数据信息

给定一个数集A,现在你需要构造一个长度为k的序列B,序列B的元素从数集A中任意挑选,要求B中任意相邻的两个数字的异或值二进制表示中1的个数是3的倍数,

请问B的有多少种合法的构造方案?两种方案不同当且仅当存在B[i]在A中的位置不同。

输入格式

 

第一行两个数字n和k,表示数集大小和序列B的长度, 接下来一行有n个数字,代表数集中的元素。

100%的数据:1≤n≤100,1≤k≤10^18,0≤a[i]≤10^18

 

输出格式

 

输出一行,表示答案,由于答案可能会很大,请对10^9+7取模后输出。

 

输入/输出例子1

输入:

5 2

15 1 2 4 8

 

输出:

13

 

输入/输出例子2

输入:

5 1

15 1 2 4 8

 

 

输出:

5

 

样例解释

 

 

一样,先考虑dp

f(i, j)表示:b序列构造出来了长度为i,第i个数放的是a[j]的构造方案数量

考虑从i-1的位置转移

假设i-1的位置放了a[k],要满足
cnt(a[k]^a[j]) %3 == 0

才能转移:
f(i, j) += f(i-1, k)

从数据入手,看到n很小。可以预处理合法的a[i], a[j]

 

 

现在考虑矩阵加速,但是dp是两维的。
第一维是阶段,可以把第一维舍弃。

假设,当前已经构造了i-1的长度
f(1) : 放a[1]的方案数, f(2): 放a[2]的方案数 .....
b[i-1] : a[1], a[2]......

那么现在要求i长度时f(1)'~f(n)'
f(1)' : 放a[1]的方案数, f(2)': 放a[2]的方案数 .....
b[i]=a[1], a[2].......
已知:
[ f(1), f(2), f(3) ......, f(n) ] * [] = [ f(1)', f(2)' ....., f(n)']

假设a[1]和a[2], a[3], a[5]合法。
那么f(1)'可以由2,3,5转移
矩阵就是
[0 .....
[1 .....
[1 ....
[0 ....
[1 .....


我们就可以填矩阵了,然后快速幂,就完事了。

 

#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N=105, Mod=1e9+7;


struct mp
{
	int n, m;
	int a[N][N];
	
	void init(int row, int col, bool isI)
	{
		n=row, m=col;
		memset(a, 0, sizeof a);
		
		if (isI)
			for (int i=1; i<=row; i++) a[i][i]=1;
	}	
}A, B;
mp operator * (const mp A, const mp B)
{
	mp C;
	C.init(A.n, B.m, 0);
	for (int i=1; i<=A.n; i++)
		for (int j=1; j<=B.m; j++)
			for (int k=1; k<=A.m; k++)
				C.a[i][j]=(C.a[i][j]+A.a[i][k]*B.a[k][j])%Mod;
		
	return C;
}
mp qpow_mp(mp A, int k)
{
	mp res;
	res.init(A.n, A.m, 1);
	while (k>0)
	{
		if (k&1) res=res*A;
		A=A*A;
		k>>=1;
	}
	
	return res;
}
int n, k, a[N], ans=0;
int count(int x)
{
	int res=0;
	while (x>0)
	{
		if (x&1) res++;
		x>>=1;
	} 
	
	return res;
}
signed main()
{
	scanf("%lld%lld", &n, &k);
	B.init(n, n, 0);
	
	for (int i=1; i<=n; i++) scanf("%lld", &a[i]);
	for (int i=1; i<=n; i++)
		for (int j=1; j<=n; j++)
			if (count(a[i]^a[j])%3==0) B.a[i][j]=1;
	
	A.init(1, n, 0);
	for (int i=1; i<=n; i++) A.a[1][i]=1;
	
	A=A*qpow_mp(B, k-1);
	
	for (int i=1; i<=n; i++) ans=(ans+A.a[1][i])%Mod;
	
	printf("%lld", ans);
	return 0;
}

  

 

 

标签:输出,int,res,矩阵,.....,序列,dp
From: https://www.cnblogs.com/didiao233/p/18365988

相关文章

  • (nice!!!)LeetCode 552. 学生出勤记录 II(动态规划dp递归版、记忆化dfs)
    题目:552.学生出勤记录II思路:记忆化搜索dfs,细节看注释classSolution{public:constintmod=1e9+7;//状态f[u][a][b]表示:在选择第u个位置前,缺勤次数为a次,且当前连续迟到次数为b次时,可以得到的合法出勤次数intf[100010][5][5];intdfs(intu,int......
  • 幸运数(dp+矩阵加速)
    第1题   幸运数 查看测评数据信息小明认为只有数字4和7是幸运数字,其他数字都不是。如果一个整数的每个数字都是幸运数字,那么该整数就是幸运整数。给出一个数组numbers[1...n]。一个长度为L的幸运数列A[0],A[1],A[2],...A[L-1]必须同时满足:1、对于0<=i<L,    A[......
  • 对象流,序列化和反序列化 day18
    packagecom.shujia.day18.ketang;importjava.io.*;/*序列化流:序列化:将一个对象转换成网络中传输的流对象输出流:ObjectOutputStream将一个类的对象写进文本中反序列化:将网络中传输的流还原成一个对象对象输入流:Object......
  • JAVA中的序列化
    Java序列化是一种机制,它可以将对象状态转换为可存储或可传输的形式。序列化后的对象可以在网络上传输,或者保存到文件、数据库等存储介质中。在Java中,序列化通过实现 java.io.Serializable接口来实现。本文将详细介绍Java序列化的概念、实现方式、优缺点以及代码示例。一、序......
  • JAVA中的反序列化
    Java反序列化是将之前序列化存储的对象状态信息重新恢复为Java对象的过程。这个过程与序列化是相反的,它允许程序从字节流中重建对象,这对于网络传输、对象持久化以及分布式系统中的对象传递至关重要。下面将详细介绍Java反序列化的概念、实现方式、安全注意事项,并通过一个......
  • 呆头鹅矩阵系统:短视频运营的创新之选——下载-官网-源码
    在短视频占据互联网重要地位的当下,呆头鹅矩阵系统以其创新的功能和可靠的保障,成为企业打开知名度、实现精准获客的强大工具。呆头鹅矩阵系统为用户提供了高效的短视频矩阵管理方案。它如同一个强大的指挥中心,将多个短视频平台的账号集中管理,无需繁琐地在多个手机上切换登录账......
  • 螺旋矩阵(LeetCode)
    题目给你一个 m 行 n 列的矩阵 matrix ,请按照 顺时针螺旋顺序 ,返回矩阵中的所有元素。解题defspiralOrder(matrix):ifnotmatrixornotmatrix[0]:return[]top,bottom=0,len(matrix)-1left,right=0,len(matrix[0])-1......
  • DP学习笔记
    动态规划算法与分治法类似,是将待求解的问题分解为若干个子问题(阶段),按顺序求解子阶段,前一子问题的解,为后一子问题的求解提供了有用的信息。在求解任一子问题时,列出各种可能的局部解,通过决策保留那些有可能达到最优的局部解,丢弃其他局部解。依次解决各子问题,最后一个子问题就是初始......
  • 【动态规划、dp】[CSP-J 2022] 上升点列 题解
    题目描述在一个二维平面内,给定nnn个整数点(xi......
  • 序列建模之循环和递归网络 - 递归神经网络篇
    序言在序列建模的广阔领域中,递归神经网络(Recursive Neural Network, RNN\text{RecursiveNeuralNetwork,RNN}Recursive Neural Network, RNN),注意此处的......