首页 > 其他分享 >幸运数(dp+矩阵加速)

幸运数(dp+矩阵加速)

时间:2024-08-18 19:48:31浏览次数:7  
标签:f1 cnt f3 int 矩阵 f2 长度 幸运 dp

第1题     幸运数 查看测评数据信息

小明认为只有数字4和7是幸运数字,其他数字都不是。

如果一个整数的每个数字都是幸运数字,那么该整数就是幸运整数。

给出一个数组numbers[1...n]。

一个长度为L的幸运数列A[0],A[1],A[2],...A[L-1]必须同时满足:

1、对于0<=i<L,       A[i]必须是幸运整数。

2、对于0<=i<L-1,A[i]的最后一个数字必须等于A[i+1]的第一个数字。

3、 对于0<=i<L,     至少存在一个下标j满足A[i] = numbers[j]。

输出有多少个不同的长度为L的幸运序列,答案模1234567891。

提示:对于两个长度都是L的幸运序列A[0], A[1], ..., A[L- 1] 和 B[0], B[1], ..., B[L - 1],他们被认为是不同序列的条件是:存在一个下标i, 使得A[i] != B[i] 

输入格式

 

第一行,两个整数,n和L。 1<=n<=50,  1<=L<=1e9。

第二行,n个整数,第i个整数是numbers[i], 1<=numbers[i]<=1e9。

 

输出格式

 

一个整数

 

输入/输出例子1

输入:

3 3

47 74 47 

 

输出:

2

 

输入/输出例子2

输入:

5 47

100 4774 200 747 300

 

输出:

2

 

样例解释

 

 

首先,根据题意,我们先初始化,后面方便d

1.筛除不含4,7的数
2.去重

3.分类-4类
1) 4开头4结尾
2) 4开头7结尾
3) 7开头4结尾
4) 7开头7结尾

 

然后就很容易定出dp了

f(i, j): 当前已经构造的长度是i,并且第i个数是第j类

 

假设

cnt1表示 有多少个第一类
cnt2表示有多少个第二类

cnt3,cnt4以此类推

 

那么可以推出转移方程
f(L, 1)=( f(L-1, 1)+f(L-1, 3) ) * cnt1
f(L, 2)=( f(L-1, 1)+f(L-1, 3) ) * cnt2
f(L, 3)=( f(L-1, 2)+f(L-1, 4) ) * cnt3
f(L, 4)=( f(L-1, 2)+f(L-1, 4) ) * cnt4

 

举个例:

f(L, 3)表示长度为L,第L个数是第3类的(7开头,4结尾)

那么 L 肯定由 L-1 转移转移过来的。由于第L个数是7开头的,那么L-1个数肯定是7结尾的,然后我们考虑第L这一位,它可以从7开头7结尾的数中任选一个,也就是要乘上cnt3

剩余的同上。

 

推完dp后,可以开始矩阵加速了

 

由于平常的矩阵都是一维的,这里却是二维,不好算
我们考虑降维,我们把第一维拆分成阶段,(矩阵不断递推,不就算作为阶段么)第二维成为矩阵中的内容

 

[f1, f2, f3, f4]
假设当前已构造的长度是L


f1:长度是L的第1类的方案数
f2:长度是L的第2类的方案数
f3:长度是L的第3类的方案数
f4:长度是L的第4类的方案数

 

目标矩阵长度就是L+1
[f1', f2', f3', f4']
f1':长度是L+1的第1类的方案数
......

 

f1' = cnt1*f1+ cnt1*f3
f2' = cnt2*f1+ cnt2*f3

......(跟dp一个样,没啥好补充的了)

 

[f1, f2, f3, f4] * [B] = [f1', f2', f3', f4']

[B]:(根据上面的式子即可求出)

[cnt1,  cnt2,  0,       0 ]
[0,      0,       cnt3,   cnt4 ]
[cnt1, cnt2, 0,         0]
[0,      0,      cnt3,     cnt4]


答案:
[f1, f2, f3, f4]*[B]^(L-1)

ans=f1+f2+f3+f4

 

#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N=55, Mod=1234567891;

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, m, L, x, a[N], cnt[N];
signed main()
{
	scanf("%lld%lld", &n, &L);
	for (int i=1; i<=n; i++)
	{
		int t=0;
		bool ok=1;
		scanf("%lld", &x);
		
		t=x;
		while (t>0)
		{
			if (t%10!=4 && t%10!=7)
			{
				ok=0;
				break;
			}
			t/=10;
		}
		
		if (ok) a[++m]=x;
	} 
//	printf("{%d}", m);
	sort(a+1, a+1+m);
	m=unique(a+1, a+1+m)-a-1;
	
//	printf("{%d}", m);
	for (int i=1; i<=m; i++)
	{
		int t=a[i], fst=0, lst=0;
		
		while (t>0)
		{
			if (fst==0) fst=t%10;
			lst=t%10;
			t/=10;
		}
		
		if (fst==4 && lst==4) cnt[1]++;
		if (fst==4 && lst==7) cnt[2]++;
		if (fst==7 && lst==4) cnt[3]++;
		if (fst==7 && lst==7) cnt[4]++;
	}
	
	A.init(1, 4, 0);
	A.a[1][1]=cnt[1], A.a[1][2]=cnt[2], A.a[1][3]=cnt[3], A.a[1][4]=cnt[4];
	
	B.init(4, 4, 0);
	B.a[1][1]=cnt[1], B.a[1][2]=cnt[2], B.a[1][3]=0,      B.a[1][4]=0;
	B.a[2][1]=0,      B.a[2][2]=0,      B.a[2][3]=cnt[3], B.a[2][4]=cnt[4];
	B.a[3][1]=cnt[1], B.a[3][2]=cnt[2], B.a[3][3]=0,      B.a[3][4]=0;
	B.a[4][1]=0,      B.a[4][2]=0,      B.a[4][3]=cnt[3], B.a[4][4]=cnt[4];
	
	A=A*qpow_mp(B, L-1);
	
	printf("%lld", (((A.a[1][1]+A.a[1][2])%Mod+A.a[1][3])%Mod+A.a[1][4])%Mod);
	return 0;
}

  

 

 

 

标签:f1,cnt,f3,int,矩阵,f2,长度,幸运,dp
From: https://www.cnblogs.com/didiao233/p/18365985

相关文章

  • 呆头鹅矩阵系统:短视频运营的创新之选——下载-官网-源码
    在短视频占据互联网重要地位的当下,呆头鹅矩阵系统以其创新的功能和可靠的保障,成为企业打开知名度、实现精准获客的强大工具。呆头鹅矩阵系统为用户提供了高效的短视频矩阵管理方案。它如同一个强大的指挥中心,将多个短视频平台的账号集中管理,无需繁琐地在多个手机上切换登录账......
  • 螺旋矩阵(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......
  • 24.8.18 DP训练
    A-Mondriaan'sDream求用\(1\times2\)的小矩形填满\(n\timesm\)的矩形的方案数sol数据范围超级小,考虑状压记录\(st_i\)表示\(i\)这个二进制状态下的连续\(0\)长度是否存在奇数设\(dp_{i,j}\)表示到第\(i\)列,且在\(j\)中\(1\)的位置和\(i+1\)列放了横......
  • 旋转矩阵的行列式为什么一定要等于1?
    一.为什么旋转矩阵要等于1?旋转概念:“旋转”就是一种没有拉伸或压缩的变换,|A|就只能是±1中的一个了。成为旋转矩阵的条件:正常情况下,求的旋转矩阵是不会出现-1这种情况的。det®=-1则表明R无效。解释:一个矩阵要能成为一个旋转矩阵,则它在构造上必定是正交矩阵,同时还是矩阵的每个......
  • dp题单vjudge 8.17
    HDU-1024MaxSumPlusPlushttps://acm.hdu.edu.cn/showproblem.php?pid=1024可以想到用dp过,但是无论时间和空间都不够,然后就不会了https://www.cnblogs.com/wuwangchuxin0924/p/6546901.html先写出转移方程,然后发现如果把其中一部分用其他的东西储存起来,就不需要重复寻找,直......
  • 状压DP 前置 位运算
    功能1:判断一个数字\(x\)二进制下第\(i\)位是不是等于\(1\)if((1<<(i-1))&x)将1左移i-1位,相当于制造了一个只有第i位上是1,其他位上都是0的二进制数。然后与x做与运算如果结果\(>0\)说明x第i位上是1,反之是0功能2:将一个数字x二进制下第i位更改成1x=x|(1<<(i-1))......
  • 酉矩阵的定义和性质
    酉矩阵,又称为幺正矩阵,是线性代数中的一个重要概念。在复数空间中,酉矩阵具有与实数空间中的正交矩阵相似的性质。下面,我们将详细解释酉矩阵的定义和性质。首先,我们来定义酉矩阵。一个n阶复方阵U如果满足U的共轭转置矩阵U^H与U的乘积等于n阶单位矩阵I,即U^H*U=I,那么U就被称为酉......
  • 详细揭秘:区间 DP 小计
    状态设计例:沉玉谷\(n\)个有色小球排成一行,第\(i\)个小球颜色为\(c_i\),每次可以拿走连续一段颜色相同的小球,问有多少种方式取完所有小球。\(n\le50\)。考虑如何求一个区间的答案:枚举与\(l\)一同删去的最右的小球。不相交区间之间没有影响,所以还要多一维表示取了几次。......