POJ2720 Last Digits
题目大意:求函数f(i) (f(0) = 1,f(x) = bf(x-1))的后7位。给定b和i。
这个要用到欧拉降幂公式。不过这个题其实比昨天的还要麻烦一些,昨天那个因为是无限的,所以每次指数肯定要大于φ(m),所以直接用就行啦。不过这个如果指数小于φ(m)的话,那么我们就得直接去取模。
这个需要特判,我们发现其实只有少数情况需要这么做,所以我们打了表(情况在代码里能看到)。
之后因为这个题的数据组数很多,如果我们每次计算的话很可能超时,我们考虑记忆化,用f[i][j]表示递归到底数为i,指数为j时候的答案,然后我们递归求解即可。
哦还有此题在POJ上数据过水……我一开始交了一份错的都过了,而且是递归的时候模数错了,我都不知道怎么对的。所以说本来我们要求出所以1~107的欧拉函数,但是有可能会T(因为本题还有其他复杂操作),因为要用的大的都是固定的,可以直接打表,小的慢慢筛。
看一下代码。
#include<cstdio> #include<algorithm> #include<cstring> #include<cmath> #include<iostream> #include<queue> #define rep(i,a,n) for(int i = a;i <= n;i++) #define per(i,n,a) for(int i = n;i >= a;i--) #define enter putchar('\n') using namespace std; typedef long long ll; const int M = 10000000; const int N = 1000005; const ll INF = 1000000000009; ll read() { ll ans = 0,op = 1; char ch = getchar(); while(ch < '0' || ch > '9') { if(ch == '-') op = -1; ch = getchar(); } while(ch >= '0' && ch <= '9') { ans *= 10; ans += ch - '0'; ch = getchar(); } return ans * op; } ll p[N],phi[M+20],tot,f[105][105],n,q,b,cnt,num[15],ans; bool np[N]; ll qpow(ll a,ll b,ll mod) { ll p = 1; while(b) { if(b&1) p *= a,p %= mod; a *= a,a %= mod; b >>= 1; } return p; } void init() { rep(i,1,6) f[i][2] = qpow(i,i,M); rep(i,1,3) f[i][3] = qpow(i,qpow(i,i,M),M); f[2][4] = qpow(2,qpow(2,qpow(2,2,M),M),M); } void euler() { phi[M] = (N-5) << 2; phi[(N-5)<<2] = 1600000; phi[1600000] = 640000; np[1] = 1; rep(i,2,N-5) { if(!np[i]) p[++tot] = i,phi[i] = i - 1; for(int j = 1;i * p[j] <= N-5;j++) { np[p[j] * i] = 1; if(!(i % p[j])) { phi[i * p[j]] = phi[i] * p[j]; break; } else phi[i * p[j]] = phi[i] * (p[j]-1); } } } ll solve(ll dep,ll mod) { if(dep == 1) return b; if(mod == 1) return 0; if(f[b][dep] != -1) return f[b][dep] % mod; ll cur = phi[mod]; ll cur1 = solve(dep-1,cur); ll cur2 = qpow(b,cur1+cur,mod); f[b][dep] = cur2; return cur2 % mod; } int main() { memset(f,-1,sizeof(f)); euler(),init(); while(scanf("%lld",&b) != EOF) { if(!b) break; cnt = 0; memset(num,0,sizeof(num)); n = read(),q = read(); if(!q) { printf("0\n"); continue; } ll now = q; q = qpow(10,q,INF); if(f[b][n] != -1) ans = f[b][n]; else ans = f[b][n] = solve(n,M); while(ans) num[++cnt] = ans % 10,ans /= 10; per(i,now,1) printf("%d",num[i]);enter; } return 0; }
当你意识到,每个上一秒都成为永恒。