POJ 4010 - 2011

http://poj.grids.cn/practice/4010/

/**********************************************************************************
4010 - 2011

时间限制:
    1000ms
内存限制:
    65536kB

描述
    已知长度最大为200位的正整数n,请求出2011^n的后四位。
输入
    第一行为一个正整数k,代表有k组数据,k<=200接下来的k行,

    每行都有一个正整数n,n的位数<=200
输出
    每一个n的结果为一个整数占一行,若不足4位,去除高位多余的0
样例输入

    3
    5
    28
    792

样例输出

    1051
    81
    5521
*********************************************************************************
*/

/**********************************************************************************
解题思路:

    abcd
    abcd
    .......
    abcd
    abcd
    abcd
  *abcd
-----------
....ABCD

假设一个数(abcd)^n的结果的后四位是:ABCD,那么可以得到:
D = ( d^n )%10                                      进位t1 = (d^n) / 10
C = ( n*c*(d^(n-1)) + t1 ) % 10                进位t2 =  ( n*c*d^(n-1) + t1 ) / 10
B = ( n*b*(d^(n-1)) + (n*(n-1)/2)*(c^2)*(d^(n-1)) + t2 ) % 10         进位t3
A = ( n*a*(d^(n-1)) + (n*(n-1)/2)*b*c*(d^(n-2)) + (n*(n-1)*(n-2)/6)*(c^3)*(d^(n-3)) + t3 )%10

其中:(n*(n-1)/2)表示组合数Cn2, (n*(n-1)*(n-2)/6)表示组合数Cn3。
由于a = 2, b = 0, c = 1, d = 1已知,那么带入可得:
D = 1,  t1 = 0
C = n%10, t2= n / 10
B = ( n*(n-1)/2 + t2 ) % 10, t3 =  ( n*(n-1)/2 + t2 ) / 10
A = ( 2*n +  n*(n-1)*(n-2)/6 + t3) % 10

带入样例输入可知正确性。

最后的难度在于n太大了,有200位,我们可以考虑是不是存在一个数t,使得:
(2011)^t 的末四位仍然是2011??
那么就是解方程令D = 1, C = 1, B = 0, A = 2求出t>1的最小正整数,我们尝试t = 1001,满足要求。
再尝试t = 101不满足。再尝试501满足。所以就可以对所有的n,我们取末三位再模除500。
注意,t = 500时候,(2011)^t的末四位就是0001。所以(2011)^(t+1)的末四位就是2011.
*********************************************************************************
*/

#include 
<iostream>
#include 
<cmath>
#include 
<cctype>
#include 
<string>
#include 
<map>
#include 
<set>
#include 
<vector>
#include 
<algorithm>
#include 
<list>
//#include <stdlib.h>
//#include <iomanip>

using namespace std;

int main()
{
    
int k, n, len, ans;
    
int a[4], t2, t3;
    
string str;
    cin 
>> k;
    
for (int i = 0; i < k; i++)
    {
        cin 
>> str;
        len 
= str.length();
        n 
= 0;
        
for (int j = len-1, t = 1; j >= 0 && j >= len - 3; j--)
        {
            n 
+= (str[j] - '0'* t;
            t 
*= 10;
        }
        n 
%= 500;

        a[
0= 1;
        a[
1= n%10;
        t2
= n/10;
        a[
2= n*(n-1)/2 + t2;
        t3 
= a[2]/10;
        a[
2%= 10;
        a[
3= ( 2*+  n*(n-1)*(n-2)/6 + t3) % 10;

        ans 
= a[0+ a[1]*10 + a[2]*100 + a[3]*1000;

        cout 
<< ans << endl;
    }

    
return 0;
}


 

posted @ 2010-11-12 21:32  InfantSorrow  阅读(539)  评论(0编辑  收藏  举报