【矩阵快速幂专题】HDU 6030 Happy Necklace

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qian2213762498/article/details/82154410

http://acm.hdu.edu.cn/showproblem.php?pid=6030

Happy Necklace

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)
Total Submission(s): 1818    Accepted Submission(s): 755

Problem Description

Little Q wants to buy a necklace for his girlfriend. Necklaces are single strings composed of multiple red and blue beads.
Little Q desperately wants to impress his girlfriend, he knows that she will like the necklace only if for every prime length continuous subsequence in the necklace, the number of red beads is not less than the number of blue beads.
Now Little Q wants to buy a necklace with exactly n beads. He wants to know the number of different necklaces that can make his girlfriend happy. Please write a program to help Little Q. Since the answer may be very large, please print the answer modulo 109+7.
Note: The necklace is a single string, {not a circle}.

Input

The first line of the input contains an integer T(1≤T≤10000), denoting the number of test cases.
For each test case, there is a single line containing an integer n(2≤n≤1018), denoting the number of beads on the necklace.

Output

For each test case, print a single line containing a single integer, denoting the answer modulo 109+7.

Sample Input

2
2
3

Sample Output

3
4

Source

2017中国大学生程序设计竞赛 - 女生专场

题意理解

给你一个长度为n的字符串,只包含0和1,要求这个字符串的所有素数长度的子序列(2,3)都是1的个数比0的个数多,问长度为n的这样字符串有多少个?

思路

 首先我们发现,当满足素数区间2,素数区间3的条件之后,下一个素数区间5乃至于之后的所有都会满足。(因为满足素数区间2,素数区间3的条件更强) 然后我们假设现在有一个数目为n的方案数为f(n)。假设红的为1 蓝的为0 从而将此题简化成满足1的个数大于等于0的个数的一个二进制字符串的方案数) 那么我们考虑一下,能否从f(n-1)转移到f(n)呢? 
考虑这个n-1位,后边如果加一个1,那么一定符合条件。(所以方案数可以加一个f(n-1)) 
那。如果最后一位加的是0呢? 此时我们不难发现,倒数第二位一定是1,只有这样才能满足素数区间2的条件。 
进而得出倒数第三位一定是1,否则不能满足素数区间3的条件。 所以我们得出结论:f(n) = f(n-1) + f(n-3) 
但是还没完,n的范围太大,我们无法将递推得到的结果保存起来。然而每次都递推又太慢,所以:矩阵快速幂。 

原矩阵、递推矩阵:(因为递推1次得到F(5),递推2次得到F(6),若得到F(n),需要递推(n-4)次



AC Code

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
typedef long long ll;
const ll nmax=3;
const ll MOD=1e9+7;
#define mod(x) ((x)%MOD)
 
int n;
struct mat{
	ll m[nmax][nmax];
}unit;
 
//A*B^(n-2)=C //C矩阵的首项即为f(n) 
mat operator *(mat a,mat b){
	mat ret;
	ll x;
	for(ll i=0;i<nmax;i++){//3*3
		for(int j=0;j<nmax;j++){
			x=0;
			for(ll k=0;k<nmax;k++){
				x+=mod((ll)a.m[i][k]*b.m[k][j]);
			}
			ret.m[i][j]=mod(x);
		}
	}
	return ret;
}
 
void init_unit(){
	for(ll i=0;i<nmax;i++){
		unit.m[i][i]=1;
	} 
	return;
}
mat pow_mat(mat a,ll n){//求矩阵a的n次幂 
	mat ret=unit;
	while(n){
		if(n&1) ret=ret*a;
		a=a*a;
		n>>=1;
	} 
	return ret;
}
int main(int argc, char** argv) {
	ll n,t;
	init_unit();
	scanf("%lld",&t);
	while(t--){//需要求矩阵B的n-2次幂 
		scanf("%lld",&n);
		if(n==2) printf("3\n");
		else if(n==3) printf("4\n");
		else if(n==4) printf("6\n");
		else{
			mat a,b;
			b.m[0][0]=1;b.m[0][1]=1;b.m[0][2]=0;
			b.m[1][0]=0;b.m[1][1]=0;b.m[1][2]=1;
			b.m[2][0]=1;b.m[2][1]=0;b.m[2][2]=0;
			
			a.m[0][0] = 6,a.m[0][1] = 4,a.m[0][2] = 3;
            a.m[1][0] = 0,a.m[1][1] = 0,a.m[1][2] = 0;
            a.m[2][0] = 0,a.m[2][1] = 0,a.m[2][2] = 0;
			b=pow_mat(b,n-4);
			a=a*b;
			//printf("%lld\n",mod(a.m[0][0]));
			printf("%lld\n",a.m[0][0]%MOD);
		} 
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qian2213762498/article/details/82154410
今日推荐