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*(n-1)*(n-2)/6 + t3) % 10;
ans = a[0] + a[1]*10 + a[2]*100 + a[3]*1000;
cout << ans << endl;
}
return 0;
}
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*(n-1)*(n-2)/6 + t3) % 10;
ans = a[0] + a[1]*10 + a[2]*100 + a[3]*1000;
cout << ans << endl;
}
return 0;
}