G. GCD Festival(莫比乌斯反演)

题目地址
真是道好题…
题目很直白了,推式子题,开推。
∑ i = 1 n ∑ j = 1 n g c d ( i , j ) ⋅ g c d ( a [ i ] , a [ j ] ) \sum_{i=1}^n\sum_{j=1}^ngcd(i,j)·gcd(a[i],a[j]) i=1nj=1ngcd(i,j)gcd(a[i],a[j])
后面的gcd(a[i],a[j])好像不是很好处理,但前面的gcd(i,j)是经典套路,所先把他们分开。
∑ d = 1 n d ∑ i = 1 n ∑ j = 1 n [ g c d ( i , j ) = = d ] ⋅ g c d ( a [ i ] , a [ j ] ) \sum_{d=1}^nd\sum_{i=1}^n\sum_{j=1}^n[gcd(i,j)==d]·gcd(a[i],a[j]) d=1ndi=1nj=1n[gcd(i,j)==d]gcd(a[i],a[j])
∑ d = 1 n d ∑ i = 1 n / d ∑ j = 1 n / d [ g c d ( i , j ) = = 1 ] ⋅ g c d ( a [ i ∗ d ] , a [ j ∗ d ] ) \sum_{d=1}^nd\sum_{i=1}^{n/d}\sum_{j=1}^{n/d}[gcd(i,j)==1]·gcd(a[i*d],a[j*d]) d=1ndi=1n/dj=1n/d[gcd(i,j)==1]gcd(a[id],a[jd])
∑ d = 1 n d ∑ i = 1 n / d ∑ j = 1 n / d ∑ d ′ ∣ g c d ( i , j ) m u [ d ′ ] ⋅ g c d ( a [ i ∗ d ] , a [ j ∗ d ] ) \sum_{d=1}^nd\sum_{i=1}^{n/d}\sum_{j=1}^{n/d}\sum_{d'|gcd(i,j)}mu[d']·gcd(a[i*d],a[j*d]) d=1ndi=1n/dj=1n/ddgcd(i,j)mu[d]gcd(a[id],a[jd])
∑ d = 1 n d ∑ d ′ = 1 n m u [ d ′ ] ∑ i = 1 n / d d ′ ∑ j = 1 n / d d ′ g c d ( a [ i ∗ d d ′ ] , a [ j ∗ d d ′ ] ) \sum_{d=1}^nd\sum_{d'=1}^nmu[d']\sum_{i=1}^{n/dd'}\sum_{j=1}^{n/dd'}gcd(a[i*dd'],a[j*dd']) d=1ndd=1nmu[d]i=1n/ddj=1n/ddgcd(a[idd],a[jdd])
令T=dd’
∑ T = 1 n ∑ d ′ ∣ T T / d ′ ⋅ m u [ d ′ ] ∗ ∑ i = 1 n / T ∑ j = 1 n / T g c d ( a [ i ∗ T ] , a [ j ∗ T ] ) \sum_{T=1}^n\sum_{d'|T}T/d'·mu[d']*\sum_{i=1}^{n/T}\sum_{j=1}^{n/T}gcd(a[i*T],a[j*T]) T=1ndTT/dmu[d]i=1n/Tj=1n/Tgcd(a[iT],a[jT])
前面是狄利克雷卷积,直接转成欧拉函数。
∑ T = 1 n p h i [ T ] ∗ ∑ i = 1 n / T ∑ j = 1 n / T g c d ( a [ i ∗ T ] , a [ j ∗ T ] ) \sum_{T=1}^nphi[T]*\sum_{i=1}^{n/T}\sum_{j=1}^{n/T}gcd(a[i*T],a[j*T]) T=1nphi[T]i=1n/Tj=1n/Tgcd(a[iT],a[jT])
然后推后半部分,首先考虑 ∑ i = 1 n ∑ j = 1 n g c d [ a [ i ] , a [ j ] ] 怎 么 推 \sum_{i=1}^n\sum_{j=1}^ngcd[a[i],a[j]]怎么推 i=1nj=1ngcd[a[i],a[j]]
其实差不多的,主要得敢推下去。
∑ d = 1 d ∑ i = 1 n ∑ j = 1 n [ g c d ( a [ i ] , a [ j ] ) = = d ] \sum_{d=1}d\sum_{i=1}^n\sum_{j=1}^n[gcd(a[i],a[j])==d] d=1di=1nj=1n[gcd(a[i],a[j])==d]
∑ d = 1 d ∑ i = 1 n ∑ j = 1 n [ g c d ( a [ i ] / d , a [ j ] / d ) = = 1 ] \sum_{d=1}d\sum_{i=1}^n\sum_{j=1}^n[gcd(a[i]/d,a[j]/d)==1] d=1di=1nj=1n[gcd(a[i]/d,a[j]/d)==1]
∑ d = 1 d ∑ i = 1 n ∑ j = 1 n ∑ d ′ ∣ g c d ( a [ i ] / d , a [ j ] / d ) m u [ d ′ ] \sum_{d=1}d\sum_{i=1}^n\sum_{j=1}^n\sum_{d'|gcd(a[i]/d,a[j]/d)}mu[d'] d=1di=1nj=1ndgcd(a[i]/d,a[j]/d)mu[d]
∑ d = 1 ∑ d ′ = 1 n m u [ d ′ ] ⋅ d ∑ i = 1 n ∑ j = 1 n [ d d ′ ∣ a [ i ] & d ′ d ∣ a [ j ] ] \sum_{d=1}\sum_{d'=1}^nmu[d']·d\sum_{i=1}^n\sum_{j=1}^n[dd'|a[i] \& d'd|a[j]] d=1d=1nmu[d]di=1nj=1n[dda[i]&dda[j]]
令T=dd’;
∑ T = 1 n ∑ d ′ ∣ T T / d ′ ⋅ m u [ d ′ ] ∑ i = 1 n ∑ j = 1 n [ T ∣ a [ i ] & T ∣ a [ j ] ] \sum_{T=1}^n\sum_{d'|T}T/d'·mu[d']\sum_{i=1}^n\sum_{j=1}^n[T|a[i] \& T|a[j]] T=1ndTT/dmu[d]i=1nj=1n[Ta[i]&Ta[j]]
前后部分合一起。
∑ T = 1 n p h i [ T ] ∑ t = 1 p h i [ t ] ∑ i = 1 n ∑ j = 1 n [ T ∣ a [ i ∗ T ] & T ∣ a [ j ∗ T ] ] \sum_{T=1}^nphi[T]\sum_{t=1}phi[t]\sum_{i=1}^n\sum_{j=1}^n[T|a[i*T] \& T|a[j*T]] T=1nphi[T]t=1phi[t]i=1nj=1n[Ta[iT]&Ta[jT]]
∑ T = 1 n p h i [ T ] ∑ t = 1 p h i [ t ] ( ∑ i = 1 n / T [ t ∣ a [ i ∗ T ] ) 2 \sum_{T=1}^nphi[T]\sum_{t=1}phi[t](\sum_{i=1}^{n/T}[t|a[i*T])^2 T=1nphi[T]t=1phi[t](i=1n/T[ta[iT])2
推完了,然后就是各种预处理欧拉函数,预处理因数,具体看代码。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <vector>
#include <queue>
#include <set>
#include <stack>
#include <time.h>
#include <map>
#include <algorithm>
#include <fstream>
//#include <unordered_map>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int maxn = 100000 + 100;
const int INF = 0x7fffffff;
const ll mod = 1e9+7;
const ll mod1 = 998244353;
const ll base = 137;
const double Pi = acos(-1.0);
const int G = 3;
bool vis[maxn];
int prime[maxn];
int phi[maxn];
int ccnt=0;
void euler()
{   phi[1]=1;
	vis[1]=true;
	for(int i=2;i<maxn;i++)
	{
		if(!vis[i])
		{
			prime[++ccnt]=i;
			phi[i]=i-1;
		}
		for(int j=1;j<=ccnt&&prime[j]*i<maxn;j++)
		{
			vis[i*prime[j]]=true;
			if(i%prime[j]==0)
			{
				phi[i*prime[j]]=phi[i]*prime[j];
				break;
			}
			phi[i*prime[j]]=phi[i]*phi[prime[j]];
		}
	}
}
int a[maxn];
vector<int>fac[maxn];
vector<int>v;
int cnt[maxn];
int cal(vector<int>v)
{
    int s=0;
    for(auto i:v)
    {
        for(auto j:fac[i])
        {
            s=(1ll*s+1ll*phi[j]*(2ll*cnt[j]+1)%mod)%mod;
            cnt[j]++;
        }
    }
    for(auto i:v)
    {
        for(auto j:fac[i])
        {
            cnt[j]=0;
        }
    }
    return s;
}
int main()
{
    euler();
    for(int i=1;i<=100000;i++)
    {
        for(int j=i;j<=100000;j+=i)
        {
            fac[j].push_back(i);
        }
    }
    int n;
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&a[i]);
    }
    int ans=0;
    for(int i=1;i<=n;i++)
    {
        v.clear();
        for(int j=i;j<=n;j+=i)
        {
            v.push_back(a[j]);
        }
        ans=(1ll*ans+1ll*cal(v)*phi[i]%mod)%mod;
    }
    printf("%d\n",ans);
  //  system("pause");
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值