HDU 4291 A Short problem(矩阵快速幂取模求循环节)

该博客探讨了一道编程题目,涉及利用矩阵快速幂的方法解决计算g(g(g(n))) mod 10^9 + 7的问题,其中g(n)由递推关系3g(n - 1) + g(n - 2)给出,初始条件为g(1) = 1, g(0) = 0。博主注意到由于三层递归的存在,问题中可能存在循环节,因此重点在于如何找到这个循环节。" 76991160,5112153,自动化测试实践指南,"['自动化测试', '测试工具', '测试框架', '持续集成', '软件质量']

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

A Short problem

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 1554    Accepted Submission(s): 566


Problem Description
  According to a research, VIM users tend to have shorter fingers, compared with Emacs users.
  Hence they prefer problems short, too. Here is a short one:
  Given n (1 <= n <= 1018), You should solve for
g(g(g(n))) mod 109 + 7

  where
g(n) = 3g(n - 1) + g(n - 2)

g(1) = 1

g(0) = 0

 

Input
  There are several test cases. For each test case there is an integer n in a single line.
  Please process until EOF (End Of File).
 

Output
  For each test case, please print a single line with a integer, the corresponding answer to this case.
 

Sample Input
0 1 2
 

Sample Output
0 1 42837

一眼看就会想到矩阵快速幂求模,但是仔细一看数据和g(g(g(x)))有三层就想到了这一定有循环节。


求循环节

#include <stdio.h>
#define ll __int64
#define mod1 1000000007
#define mod2 222222224
#define mod3 183120
int main(){
	ll a=0,b=1,c,i;
	for(i=2;;i++){//求循环节 
		c=(b*3+a)%mod1;//mod
		a=b;
		b=c;
		if(a == 0 && b == 1){
			printf("%I64d\n",i-1);//mod2=222222224,mod3=183120
			break;
		}
	}
    return 0;
}

AC代码:

#include <stdio.h>
#include <string.h>
#define ll __int64
#define Max 2 //矩阵大小,注意能小就小  
ll n;
int mod[]={183120,222222224,1000000007};
struct Matrix{
      ll  mm[Max][Max];
}A,I,W;

Matrix matrixmul(Matrix a,Matrix b,int mod) //矩阵乘法
{
       int i,j,k;
       Matrix c;
       for (i = 0 ; i < 2; i++)
           for (j = 0; j <2;j++){
                 c.mm[i][j] = 0;
                 for (k = 0; k <2; k++)
                     c.mm[i][j] += (a.mm[i][k] * b.mm[k][j])%mod;
				  c.mm[i][j]%=mod;
             }
       return c;
}
ll quickpagow(ll n,int mod){
       Matrix m = A, b = I;//b是单位矩阵
       while (n >= 1){
             if (n & 1)
                b = matrixmul(b,m,mod);
             n = n >> 1;
             m = matrixmul(m,m,mod);
       }
	   b=matrixmul(W,b,mod);
       return b.mm[0][0]%mod;
}

int main (){
	ll i;

	A.mm[0][0]=0,A.mm[0][1]=1;
	A.mm[1][0]=1,A.mm[1][1]=3;

	I.mm[0][0]=1,I.mm[0][1]=0;
	I.mm[1][0]=0,I.mm[1][1]=1;

	W.mm[0][0]=3,W.mm[0][1]=10;
	W.mm[1][0]=0,W.mm[1][1]=0;
	while(~scanf("%I64d",&n)){
		for(i=0;i<3;i++){
			if(n>=2)
				n=quickpagow(n-2,mod[i]);
		}
		printf("%I64d\n",n);
	}
	return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值