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('
')

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

 

原文地址:https://www.cnblogs.com/captain1/p/9783945.html