|
题目链接:http://poj.org/problem?id=2720
/**//* 题意: 给定三个整数 b, n, 和 i, 定义函数 f(x) = b^f(x-1) 如果 x > 0, 并且 f(0)=1。 要求计算 f(i) 的最后n为十进制整数,并且要求输出前导零。
解法: 二分求幂 + 欧拉函数 + 素数筛选
思路: 除非b等于1的时候,否则,这个数列的增长速度很快,所以直接暴力是行不通的,这 里我们用到数论的一个结论,a^b % c = a^ (b % phi(c) + phi(c)) % c,b < phi(c)。 其中phi(c)是c的欧拉函数,也就是小于等于c并且与之互质的数的个数。 于是当b比较小的时候就可以直接采用二分求幂来做,当b很大的时候就利用这个结论 ,可以迅速将指数降下来。 这题是海量数据,如果每个数都直接算肯定会超时,我的做法是用一个数组保存下来 ,而且保存的是n等于7的值,也就是保存了整数后7为,这样可以少算6倍。最后再做处理 ,注意前导零的处理。 */
#include <iostream>
using namespace std;
#define maxn 3163 bool f[maxn]; int prime[maxn], size; int ten[8];
void Init() { int i, j; f[0] = f[1] = 1; for(i = 2; i < maxn; i++) { if(!f[i]) { prime[size++] = i; for(j = i+i; j < maxn; j += i) { f[j] = 1; } } } ten[0] = 1; for(i = 1; i <= 7; i++) { ten[i] = ten[i-1] * 10; } }
int phi(int v) { int i; int ans = 1; for(i = 0; i < size; i++) { if(!(v % prime[i])) { v /= prime[i]; while(!(v % prime[i])) { v /= prime[i]; ans *= prime[i]; } ans *= prime[i] - 1;
if(v == 1) return ans; } } return ans * (v - 1); }
int Product_Mod(int a, int b, int mod) { int S = 0; while(b) { if(b & 1) { S = (S + a) % mod; } b >>= 1; a = (a + a) % mod; } return S; }
#define ll __int64
int Exp_Mod(ll a, int b, int mod) { ll v = 1; while(b) { if(b & 1) { v *= a; if(v >= mod) v %= mod; } b >>= 1; a *= a; if(a >= mod) a %= mod; } return v; }
int hash[101][101]; int F[101][101]; int dfs(int b, int n, int mod) { if(n == 0) return 1 % mod; if(mod == 1) return 0; if(F[b][n] < 0) { int oula = phi(mod); return Exp_Mod( b, dfs(b, n-1, oula) + oula, mod); }else { return F[b][n] % mod; } }
int Test(int b, int ex) { if(ex < 0) return -1;
int i; int sum = 1; for(i = 0; i < ex; i++) { sum *= b; if(sum >= ten[7]) return -1; } return sum; }
int main() { Init(); int i, j; int bew, n, mod, ans; memset(hash, -1, sizeof(hash));
for(i = 1; i <= 100; i++) { F[i][0] = 1; for(j = 1; j <= 100; j++) { F[i][j] = Test(i, F[i][j-1]); } }
while(scanf("%d", &bew) != EOF && bew) { scanf("%d %d", &n, &mod);
if(hash[bew][n] == -1) { if(bew == 1) { ans = 1; }else { ans = dfs(bew, n, ten[7]); } hash[bew][n] = ans; } ans = hash[bew][n] % ten[mod];
for(i = 1; i <= 7; i++) { if(ans < ten[i]) { break; } }
for(i = mod-i; i ; i--) { printf("0"); } printf("%d\n", ans); } return 0; }
|