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

     

  • 相关阅读:
    工厂方法模式(2)
    单例模式(1)
    数组中任意位置添加数组
    六中设计模式中的原则总结
    开闭原则(设计模式6)
    迪米特法则(设计模式5)
    接口隔离原则(设计模式4)
    依赖倒置原则(设计模式3)
    里氏替换原则(设计模式原则2)
    相似图片搜索的原理(二) (转载)
  • 原文地址:https://www.cnblogs.com/captain1/p/9783945.html
Copyright © 2020-2023  润新知