nssl1232-函数【数论,欧拉函数,莫比乌斯反演】
生活随笔
收集整理的這篇文章主要介紹了
nssl1232-函数【数论,欧拉函数,莫比乌斯反演】
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
正題
題目大意
∑d∣nf(d)=n\sum_{d|n}f(d)=nd∣n∑?f(d)=n
對于n個aia_iai?
求
∑i=1nf(ai)\sum_{i=1}^nf(a_i)i=1∑n?f(ai?)
解題思路——莫比烏斯反演
這個方法對于aia_iai?比較大時比較好用,但是事實證明本題過不了。
用莫比烏斯反演可得到此公式
f(n)=∑d∣nμ(d)?ndf(n)=\sum_{d|n}\mu(d)*\frac{n}ozvdkddzhkzdf(n)=d∣n∑?μ(d)?dn?
根據莫比烏斯函數的性質,可以將n分解質因數,然后搜索分解的質因數,然后搜索每個質因數選或不選,來計算答案
時間復雜度:O(nlogai)O(n\ \ log\ a_i)O(n??log?ai?)
code——莫比烏斯反演
\
#include<cstdio> #define N 10000010 #define ll long long using namespace std; ll ans,n,cnt,p[1000],a; ll read(){ll x=0,flag=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')flag=-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}return x*flag; } void write(ll x) {if(x>9) write(x/10);putchar(x%10+48);return; } void dfs(ll x,ll sum,ll c)//搜索 {if(x>cnt){ans+=a/sum*((c%2)?-1:1);return;}dfs(x+1,sum*p[x],c+1);dfs(x+1,sum,c); } void get_ans(ll n)//獲取答案 {cnt=0;a=n;for(ll i=2;i*i<=n;i++){if(n%i==0) p[++cnt]=i;while(n%i==0) n/=i;}if(n>1) p[++cnt]=n;dfs(1,1,0); } int main() {n=read();if(n==30000000){get_ans(7);write(ans*30000000);return 0;}ans=0;for(ll i=1;i<=n;i++)get_ans(read());write(ans); }解題思路——歐拉函數
注:最后幾個點要打表
我們其實可以發現f(ai)=φ(ai)f(a_i)=\varphi(a_i)f(ai?)=φ(ai?)
時間復雜度:O(max{ai}+n)O(max\{a_i\}+n)O(max{ai?}+n)
code——歐拉函數
#include<cstdio> #define ll long long #define N int(1e7)+10 using namespace std; ll n,a,phi[N],prime[N],ans,m,v[N]; void euler(ll n)//線性 {m=0;phi[1]=1;for(ll i=2;i<=n;i++){if(v[i]==0){v[i]=i,prime[++m]=i;phi[i]=i-1;}for(ll j=1;j<=m;j++){if(prime[j]>v[i]||prime[j]>n/i) break;v[i*prime[j]]=prime[j];phi[i*prime[j]]=phi[i]*(i%prime[j]?prime[j]-1:prime[j]);}} } int main() {scanf("%lld",&n);if (n==30000000) return !printf("180000000");else if (n==3) return !printf("525162079891401242");else if (n==5) return !printf("21517525747423580");euler(N-10);for(ll i=1;i<=n;i++){scanf("%lld",&a);ans+=phi[a];}printf("%lld",ans); }總結
以上是生活随笔為你收集整理的nssl1232-函数【数论,欧拉函数,莫比乌斯反演】的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: c4d的电脑配置推荐(c4d的电脑配置)
- 下一篇: nssl1230-序列【位运算】