HDU-——5451 Best Solver(循环节+矩阵快速幂)

The so-called best problem solver can easily solve this problem, with his/her childhood sweetheart. 
It is known that y=(5+26–√)1+2xy=(5+26)1+2x. 
For a given integer x (0≤x<232)x (0≤x<232) and a given prime number M (M≤46337)M (M≤46337), print [y]%M[y]%M. ([y][y] means the integer part of yy) 

Input

An integer T (1<T≤1000)T (1<T≤1000), indicating there are TT test cases. 
Following are TT lines, each containing two integers xx and MM, as introduced above.

Output

The output contains exactly TT lines. 
Each line contains an integer representing [y]%M[y]%M.

Sample Input

7
0 46337
1 46337
3 46337
1 46337
21 46337
321 46337
4321 46337

Sample Output

Case #1: 97
Case #2: 969
Case #3: 16537
Case #4: 969
Case #5: 40453
Case #6: 10211
Case #7: 17947

题意:已知,给你整数x,和一个素数M,求[y]%M

题解:

首先知道 :循环节题目常见的有两种情况: MOD-1 和  MOD^2-1 通过推导或暴力可求出。

(5+2√6)^n=Xn+Yn*√6 =(Xn-1+Yn-1*√6)*(5+2√6)= 5*Xn-1 + 12*Yn-1 + (2*Xn-1 + 5*Yn-1 )*√6

对应相等得到:

Xn =  5*Xn-1 + 12*Yn-1;广义斐波那契数列形式

Yn =  2*Xn-1 + 5*Yn-1;  广义斐波那契数列形式

所以

注意:(右边括号的X,Y下标应该为n-1),简单矩阵快速幂,不说了~~(这个图是盗的,所以有点错误~~嘻嘻~~) !!!

然而√6还是一个大问题,解决办法:

(5 - 2√6)^n = Xn - Yn*√6

(5+2√6)^n=Xn+Yn*√6 + Xn - Yn*√6 - (Xn - Yn*√6) = 2*Xn - (0.101)^n  这里技巧性很强~

因为 2*Xn-1 < 2*Xn - (0.101)^n  < 2*Xn  所以[ (5+2√6)n ]= 2*Xn - 1

由于n=1+2^x ,求解取模时用到广义斐波那契数列的循环节:(MOD-1)*(MOD+1)

接下来就可以写代码了,上代码:

#include <iostream>
#include <cstring>
using namespace std;
typedef long long ll;
struct hh{
	ll a[20][20];
}x;// 储存构造矩阵以及经过运算得出来的矩阵
hh mul(hh x,hh y,int c){//矩阵快速幂
	hh w;
	memset(w.a,0,sizeof(w.a));
	for (int i = 0; i < 2;i++){
		for (int j = 0; j < 2;j++){
			for (int k = 0; k < 2;k++){
				w.a[i][j]=(w.a[i][j]%c+(x.a[i][k]%c*y.a[k][j]%c)%c)%c;
			}
		}
	}
	return w;
}
hh j_quick(hh a,ll b,ll c){//矩阵快速幂 
	hh ans;
	memset(ans.a,0,sizeof(ans.a));
	for (int i = 0; i < 2;i++){
		ans.a[i][i]=1;
	}
	while(b!=0){
		if(b&1) ans=mul(ans,a,c);
		b>>=1;
		a=mul(a,a,c);
	}
	return ans;
}
ll quick(ll a,ll b,ll c){
	ll ans=1;
	while(b){
		if(b&1) ans=(ans*a)%c;
		b>>=1;
		a=(a*a)%c;
	}
	return ans;
}
int main(){
	int cas=1;
	int t;
	scanf("%d",&t);
	while(t--){
		ll x,m;
		scanf("%d%d",&x,&m);
		hh cao;
		cao.a[0][0]=5;
		cao.a[0][1]=12;
		cao.a[1][0]=2;
		cao.a[1][1]=5;
		ll n=quick(2,x,m*m-1)+1;//循环节在这里用
		hh b = j_quick(cao,n-1,m);
		printf("Case #%d: %lld\n",cas++,(2*(5*b.a[0][0]+2*b.a[0][1])-1)%m);
	}
	return 0;
} 

 

 

全部评论

相关推荐

不愿透露姓名的神秘牛友
01-17 11:44
你在各大软件投了一份又一份,你打招呼的hr一个接一个,但是只要你投过的,很快就下线了,没关系你的能量是很强,你看过的岗位招到人的速度都增加了。朋友们一个个拿着丰厚的实习回报,你却默默在家刷新邮箱,等待着那寥寥无几的面试通知。你每天一睁眼就狂投简历,你一有面试邀约就点确认。过年亲戚们围坐聊天,谈论着他们孩子的职场成就,你试图插话说自己面试过的公司数量,但他们显然不太感兴趣。你在心里自嘲,觉得他们不懂面试的艰辛、不懂得每一次面试机会的珍贵,不懂得一张张精心准备的简历背后的努力。笑你那个小侄子只会在网上刷刷职位,而你已经是各大招聘网站的常客。亲戚们夸赞自己孩子一年的成就,儿子的新工作,女儿的晋升,而...
龚新化:这帖删了呗,这跟我朋友有点相似,不过我是无所谓的😀,没什么感觉,我不轻易破防的,但是我一个朋友可能有点汗流浃背了😕,他不太舒服想睡了,当然不是我哈,我一直都是行的,以一个旁观者的心态看吧,也不至于破防吧😃,就是想照顾下我朋友的感受,他有点破防了,还是建议删了吧😯,当然删不删随你,因为我是没感觉的,就是为朋友感到不平罢了🥺
点赞 评论 收藏
分享
01-07 15:50
四川大学 Java
明远湖摸鱼:同年级的同学,,简历可以大一点,这个有点太密集了,实习技术可以量化的尽量量化
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客企业服务