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 ;
}


 

你可能感兴趣的:(poj)