欧拉定理

第二天数论,简直听天书

 

 

 

记住就行

 

P4139:上帝与集合的正确用法:https://www.luogu.org/problemnew/show/P4139

考虑扩展欧拉定理,每次对上面的式子使用扩欧

由于对一个数不断取phi,当p为1返回0即可,所以复杂度为log(p)

考虑到原题中的式子一定比p大,所以只用考虑定理中的第二种情况即可

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include <ext/pb_ds/priority_queue.hpp>
#include<queue>
#include<map>
using namespace std;
typedef long long ll;
#define pii pair<int,int>
#define mp make_pair
#define pair_heap __gnu_pbds ::priority_queue<pii> 
#define llinf 9000000000000000000LL
#define B cout << "breakpoint" << endl;
inline 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) += ch - '0';
        ch = getchar();
    }
    return ans * op;
}
const int maxn = 1e7 + 5;
ll pri[maxn],cnt,phi[maxn];
bool vis[maxn];
void init()
{
    for(int i = 2;i <= maxn - 5;i++)
    {
        if(!vis[i]) pri[++cnt] = i,phi[i] = i - 1;
        for(int j = 1;j <= cnt && i * pri[j] <= maxn - 5;j++)
        {
            vis[i * pri[j]] = 1;
            if(i % pri[j] == 0) {phi[i * pri[j]] = phi[i] * pri[j]; break; }
            else phi[i * pri[j]] = phi[i] * phi[pri[j]]; 
        }
    }
}
ll power(ll a,ll b,ll p)
{
    ll ans = 1,res = a;
    while(b)
    {
        if(b & 1) (ans *= res) %= p;
        (res *= res) %= p;
        b >>= 1;
    }
    return ans;
}
ll solve(ll p)
{
    if(p == 1) return 0;
    return power(2,solve(phi[p]) + phi[p],p);
}
int main()
{
    ll t = read();
    init();
    while(t--)
    {
        ll p = read();
        printf("%lld\n",solve(p));
    }
}
    
    
View Code

 

CF906D:power tower:https://www.luogu.org/problemnew/show/CF906D

继续用欧拉定理,和上面一样,至多递归log层结束

不一样的是,这道题需要考虑b与phi(p)的大小关系

有两种解决方法:1.记录b是否真正被phi(p)模过,返回pair即可

2.

ll mod(ll a,ll b)
{    return a < b ? a : a % b + b; }
View Code

这样取模,结果虽然还是比b大(符合原来的情况),但是再取一遍模在计算时仍然可以得到正确答案

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<queue>
#include<map>
using namespace std;
typedef long long ll;
#define B cout << "breakpoint" << endl;
inline 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) += ch - '0';
        ch = getchar();
    }
    return ans * op;
}
const int maxn = 1e6 + 5;
map<ll,ll> phi;
ll n,p;
ll a[maxn];
ll get(ll x)
{
    ll res = x,tp = x;
    if(phi[x]) return phi[x];
    for(int i = 2;i <= sqrt(x);i++)
    {
        if(x % i == 0)
        {
            res = res / i * (i - 1);
            while(x % i == 0) x /= i;
        }
    }
    if(x > 1) res = res / x * (x - 1);
    return phi[tp] = res;
}
ll mod(ll a,ll b)
{    return a < b ? a : a % b + b; }
ll power(ll a,ll b,ll p)
{
    ll ans = 1,res = a;
    while(b)
    {
        if(b & 1) ans = mod(ans * res, p);
        res = mod(res * res,p);
        b >>= 1;
    }
    return ans;
}
ll solve(int l,int r,ll p)
{
    if(l == r || p == 1) return mod(a[l],p);
    else return power(a[l],solve(l + 1,r,get(p)),p);
}
int main()
{
    n = read();
    p = read();
    for(int i = 1;i <= n;i++) a[i] = read();
    ll q = read();
    while(q--)
    {
        ll l = read(),r = read();
        printf("%lld\n",solve(l,r,p) % p);
    }
}
View Code

 

posted on 2019-07-21 13:18  L_M_A  阅读(212)  评论(0编辑  收藏  举报

导航