Euler函数与Euler定理

欧拉函数与欧拉定理

证明&结论

https://www.cnblogs.com/lhm-/p/12229648.html

欧拉定理

容斥原理求欧拉函数(了解)

1、如果 i % p == 0 ,那么 phi (i*p) = phi (i) * p。

显然,与 i 互质的每一个数都与 i*p 互质。

2、如果 i % p != 0 , 那么 phi (i*p) = phi (i) * (p-1) 。

因为 i 与 p 互质,根据积性函数的性质,得 phi(i*p) = phi(i) * phi(p)。

又因为 p 是质数,所以 phi(p) = p-1;

暴力筛PHI

int PHI(int x){
    int res=x;
    for(int i=2;i*i<=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 res;
}

线性筛PHI

void PHI(int x){
    phi[1]=1;
    for(int i=2;i<=x;i++){
        if(!mindiv[i]) mindiv[i]=p[++p[0]]=i,phi[i]=i-1;
        for(int j=1;j<=p[0]&&i*p[j]<=x;j++){
            mindiv[i*p[j]]=p[j];
            if(i%p[j]==0){
                phi[i*p[j]]=phi[i]*p[j];
                break;
            }else phi[i*p[j]]=phi[i]*phi[p[j]];
        }
    }
}

Longge 的问题

Description

\(\gcd(i, N)(1<=i <=N)\)

Solution

枚举\(n\)的约数\(k\),令\(s(k)\)为满足\(gcd(m,n)=k,(1<=m<=n)m\)的个数,则\(ans=∑(k*s(k))\) (\(k\)\(n\)的约数)

因为\(gcd(m,n)=k\),所以\(gcd(m/k,n/k)=1\),于是\(s(k)=phi(n/k)\)

phi可以在根号的时间内求出

#include <cstdio>
#include <iostream>
#define int long long
#define M 10001000
using namespace std;
int n,ans;
int PHI(int x){
    int res=x;
    for(int i=2;i*i<=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 res;
}
signed main(){
    scanf("%lld",&n);
    for(int i=1;i*i<=n;i++){
        if(n%i==0){
            ans+=i*PHI(n/i);
            if(i*i<n) ans+=(n/i)*PHI(i);
        }
    }
    printf("%lld\n",ans);
    return 0;
} 

仪仗队

绝了的证明——戳这里

我的大致理解:

要是想要被看到,必须\(gcd(x,y)=1\)

然后我们把图沿着对角线割开,先分析下半部分(显然对角线上除了(2,2)你都看不到),答案乘2

考虑第 \(x\) 列,有多少个\(i\)\(x\) 互素(\(i<x\))——显然phi(i)

#include<bits/stdc++.h>
using namespace std;
#define N 40005
typedef long long ll;
int n;
ll phi[N],ans=3;//(2,2)(1,2)(2,1)特殊点
int main(){
    scanf("%d",&n);
    if(n==1){
    	puts("0");
    	return 0;
	}
	for(int i=1;i<=n;i++)
    	phi[i]=i;
    for(int i=2;i<=n;i++)
    	if(phi[i]==i)
    		for(int j=i;j<=n;j+=i)
    			phi[j]=phi[j]/i*(i-1);
	--n;
	for(int i=2;i<=n;i++)
		ans+=phi[i]*2;
	printf("%d\n",ans);
    return 0;
}

奇数国

题意简化:

\([1,product ]\) 中有多少数 与 product 互质(φ[product])

线段树维护区间内每个质因子是否出现过,由于只有60个质数,线段树维护二进制60位(状压)即可,并维护区间内的乘积,线段树单点修改,区间求和

不开long long 见祖宗

#include<bits/stdc++.h>
#define int long long 
using namespace std;
const int mod=19961993;
const int MAXN=1000005;
#define ls (p<<1)
#define rs (p<<1|1)
inline int read(){
	int x=0,f=1;char ch=getchar();
	while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
	while(isdigit(ch)){x=x*10+ch-'0';ch=getchar();}
	return x*f;
}
int n;
int a,b,c;
int mindiv[300],prime[65];
int inv[65];
int Fpow(int a,int b){
    int ans=1;
    while(b){
        if(b&1) ans=(ans*a)%mod;
        a=(a*a)%mod;
        b>>=1;
    }
    return ans;
}
void init(){
    for(int i=2;i<=281;i++){
        if(!mindiv[i]) prime[++prime[0]]=i,mindiv[i]=i;
        for(int j=1;j<=prime[0]&&i*prime[j]<=281&&prime[j]<=mindiv[i];j++)
            mindiv[i*prime[j]]=prime[j];
    }
    for(int i=1;i<=60;i++) inv[i]=Fpow(prime[i],mod-2);
}
int zip(int x){
    int res=0;
    for(int i=1;i<=60;i++)
        if(x%prime[i]==0) res|=(1ll<<(i-1));
    return res;
}
struct node{
    int l,r;
    int sum;
    int zy;
}t[MAXN];
void pushup(int p){
    t[p].sum=(t[ls].sum*t[rs].sum)%mod;
    t[p].zy=(t[ls].zy|t[rs].zy);
}
void build(int l,int r,int p){
    t[p].l=l,t[p].r=r;
    if(l==r){t[p].sum=3;t[p].zy=(1ll<<1);return;}//棰樻剰鍒濆鍊间负3,3鏄浜屼釜绱犳暟
    int mid=(l+r)>>1;
    build(l,mid,ls);
    build(mid+1,r,rs);
    pushup(p);
}
void modify(int pos,int v,int p){
    if(t[p].l==t[p].r&&t[p].l==pos){
        t[p].sum=v%mod;
        t[p].zy=zip(v);
        return;
    }
    int mid=(t[p].l+t[p].r)>>1;
    if(pos<=mid) modify(pos,v,ls);
    else modify(pos,v,rs);
    pushup(p);
}
int query_sum(int p,int l,int r){
    if(t[p].l==l&&t[p].r==r) return t[p].sum%mod;
    int mid=(t[p].l+t[p].r)>>1;
    if(r<=mid) return query_sum(ls,l,r)%mod;
    else if(l>mid) return query_sum(rs,l,r)%mod;
    else return (query_sum(ls,l,mid)*query_sum(rs,mid+1,r))%mod;
}
int query_zy(int p,int l,int r){
    if(t[p].l==l&&t[p].r==r) return t[p].zy;
    int mid=(t[p].l+t[p].r)>>1;
    if(r<=mid) return query_zy(ls,l,r);
    else if(l>mid) return query_zy(rs,l,r);
    else return query_zy(ls,l,mid)|query_zy(rs,mid+1,r);
}
int cal(int x,int zy){
    int res=x;
    for(int i=1;i<=60;i++)
        if(zy&(1ll<<(i-1))) 
            res=((res*inv[i]%mod)*(prime[i]-1))%mod;
    return res;
}
signed main(){
    n=read();
    init();
    build(1,100000,1);
    for(int i=1;i<=n;i++){
        a=read(),b=read(),c=read();
        if(!a) printf("%lld\n",cal(query_sum(1,b,c),query_zy(1,b,c)));
        else modify(b,c,1);
    }
    return 0;
}

扩展欧拉定理

模板

blog

边读入,边mod

#include<cstdio>
#include<iostream>
using namespace std;
#define int long long
int tmp,phi,a,m,b;
bool flag;
int qpow(int a,int b){
    int ans=1;
    while(b){
        if(b&1) ans=(ans*a)%m;
        a=(a*a)%m;
        b>>=1;
    }
    return ans;
}
signed main(){
    int i;
    char c;
    scanf("%d%d",&a,&m);
    tmp=phi=m;
    for(int i=2;i*i<=m;i++){
        if(tmp%i==0){
            phi=phi/i*(i-1);
            while(tmp%i==0) tmp/=i;
        }
    }
    if(tmp>1) phi=phi/tmp*(tmp-1);
    while(!isdigit(c=getchar())); 
    for(;isdigit(c);c=getchar()){
        b=b*10+c-'0';
        if (b>=phi){
            flag=true;
            b%=phi;
        }
    }
    if(flag) b+=phi;
    printf("%d\n",qpow(a,b));    
    return 0;
}

上帝与集合的正确用法

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define M 10001000
using namespace std;
int phi[M],p[1001001],tot;
bool not_p[M];
int PHI(int x){
    int res=x;
    for(int i=2;i*i<=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 res;
}
int qpow(long long a,long long b,int mod){
    long long ans=1;
    while(b){
        if(b&1)ans=(ans*a)%mod;
        a=(a*a)%mod;
        b>>=1;
    }
    return ans;
}
int solve(int p){
    int k=PHI(p);
    if(k==1)return 0;
    return qpow(2,(solve(k)+k),p);
}
int main(){
    int T,mod;
    scanf("%d",&T);
    while(T--){
        scanf("%d",&mod);
        printf("%d\n",solve(mod));
    }
    return 0;
} 
posted @ 2020-08-19 21:10  ke_xin  阅读(67)  评论(0编辑  收藏  举报