1. 程式人生 > >HDU 1852 Beijing 2008(快速冪+取模)

HDU 1852 Beijing 2008(快速冪+取模)

Problem Description

As we all know, the next Olympic Games will be held in Beijing in 2008. So the year 2008 seems a little special somehow. You are looking forward to it, too, aren't you? Unfortunately there still are months to go. Take it easy. Luckily you meet me. I have a problem for you to solve. Enjoy your time.

Now given a positive integer N, get the sum S of all positive integer divisors of 2008N. Oh no, the result may be much larger than you can think. But it is OK to determine the rest of the division of S by K. The result is kept as M.

Pay attention! M is not the answer we want. If you can get 2008M, that will be wonderful. If it is larger than K, leave it modulo K to the output. See the example for N = 1,K = 10000: The positive integer divisors of 20081 are 1、2、4、8、251、502、1004、2008,S = 3780, M = 3780, 2008M % K = 5776.
 

 

 

Input

The input consists of several test cases. Each test case contains a line with two integers N and K (1 ≤ N ≤ 10000000, 500 ≤ K ≤ 10000). N = K = 0 ends the input file and should not be processed.

 

 

Output

For each test case, in a separate line, please output the result.

 

 

Sample Input

 

1 10000 0 0

 

 

Sample Output

 

5776

 

題意:給你一個n和k,你要先求出2008^n的所有因子之和m,當然m是因子和對k取餘的結果,最後求 2008^m%k

思路:

// 這題主要求S
// 結論: S = (251^(n+1)-1) * (2^(3n+1)-1) / 250 
// 是兩個等比數列和相乘 
// 
// 推理:
// 2008 = 2^3 * 251 
// 所以 2008^N 有 3N 個 2 和 N 個251 
// 所有僅由2組成的因子有
// 2^0 2^1 2^2 ... 2^(3N)
// 設集合 C = {2^0, 2^1, 2^2 ...,2^(3N)};
// SUM(C) = 2^(3n+1)-1

// 跟251組合產生的因子有
// 251^0 * C
// 251^1 * C
// ...
// 251^N * C

// 所有因子和為:
// S = (251^(n+1)-1))/250 * (2^(3n+1)-1)

// 計算S%K:

// S 很大, 不能儲存在普通的資料型別中, 需要直接計算S%K
// 因為S有個分母250, 分子是(2^(3*n+1)-1)*(251^(n+1)-1),設X為這個分子,則 S = X/250

//這道題不能用乘法逆元去處理k,因為乘法逆元要求必須互素
// 要用這個公式  S%K = (X/250)%K = (X%(250*K))/250
// 變成先求餘數再除法的形式

//然後X%(250*k)又可以拆開分別來算,一步一步就搞定啦
 

AC程式碼:

#include<iostream>
#include<cstdio>
using namespace std;
int poww(int n,int m,int mod) //快速冪 
{
	long long base=n;
	long long sum=1;
	while(m)
	{
		if(m&1)
		{
			sum=sum*base%mod;
		}
		base=base*base%mod;
		m>>=1;			
	}
	return sum; 
}
int main()
{
	long long  n,k;

	while(scanf("%ld%ld",&n,&k)!=EOF)
	{
		if(!n&&!k) break;
		long long suma,sumb,sum;
		suma=poww(2,3*n+1,k*250)-1;	
		sumb=poww(251,n+1,k*250)-1;
		sum=suma*sumb/250%k;
		printf("%lld\n",poww(2008,sum,k));
	 } 
	return 0;
 }