Hdu 5451 Best Solver(快速幂取模+循环节) -2015 ACM-ICPC沈阳网赛1002

Hdu 5451 Best Solver(快速幂取模+循环节) -2015 ACM-ICPC沈阳网赛1002

Best Solver

Time Limit: 1500/1000 MS (Java/Others)    Memory Limit: 65535/102400 K (Java/Others)
Total Submission(s): 736    Accepted Submission(s): 413


Problem Description
The so-called best problem solver can easily solve this problem, with his/her childhood sweetheart.

It is known that  y=(5+26)1+2x .
For a given integer  x (0x<232)  and a given prime number  M (M46337) , print  [y]%M . ( [y]  means the integer part of  y )
 

Input
An integer  T (1<T1000) , indicating there are  T  test cases.
Following are  T  lines, each containing two integers  x  and  M , as introduced above.
 

Output
The output contains exactly  T  lines.
Each line contains an integer representing  [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
 

Source


题意: y=(5+26)1+2x .这个式子x (0<=x<2^32)和一个素数M(M<=46337),求y的整数部分对M取余的结果
分析:由斐波那契数列通项公式联想到An=(5+2√6)^n+(5-2√6)^n ,明显对任何的n,an是整数,0<(5-2√
6)^n<1,所以(5+2√6)^n-(1-(5-2√6))
即是我们要求的(5+2√6)^n的整数部分,即是An  -1。问题的关键变成了求An。
还是有由斐波那契数列通项公式的启发,设f[n]=p*f[n-1]+q*f[n-2],代入f[1],f[2],f[3]的值,可以得到p=10,
q=-1。于是我们有:
f[n]=10*f[n-1]-f[n-2]
给定x,由于x的值巨大,写程序打表,发现f[n]%M出现了循环节,所以1+2^x对循环节长度len取模后,可以求得结果。
AC代码:
#include<iostream>
#include<cstdio>
#include<sstream>
#include<cmath>
#include<cstring>
#include<string>
#include<algorithm>
#define INF 1<<29
#define eps 1e-9
#define LD long double
#define LL long long
const int maxn = 100000 + 10;
using namespace std;
int f[maxn];
int calc(int m)
{
	f[1] = 10 % m;
	f[2] = 98 % m;
	for (int i = 3;; i++)
	{
		f[i] = (10 * f[i - 1]%m - f[i - 2]%m+m) % m;
		if (f[i - 1] == 10 % m&&f[i] == 98 % m)
		{
			return i-2;
		}
	}
}
int pow_mod(int a, LL n, int m)
{
	if (n == 0) return 1;
	int x = pow_mod(a, n / 2, m);
	long long ans = (long long)x*x%m;
	if (n % 2 == 1) ans = ans*a%m;
	return (int)ans;
}
int main()
{
#ifdef LOCAL
	freopen("data.txt", "r", stdin);
#endif
	int T;
	cin >> T;
	for (int i = 1; i <= T;++i)
	{
		cout << "Case #" << i << ": ";
		int x, M;
		cin >> x >> M;
		memset(f, 0, sizeof(0));
		int len=calc(M);
		int find = (1 + pow_mod(2, x, len))%len;
		cout << (f[find]-1+M)%M<<endl;

	}
	return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值