容斥+数论
for (long long k = N; k >= 1; k--) { f[k] = (N / k) * (N / k); for (long long i = k + k; i <= N; i += k) f[k] -= f[i]; }
例题:
链接:https://ac.nowcoder.com/acm/contest/549/J
来源:牛客网
输入描述:
一行两个正整数n,m一行两个正整数n,m一行两个正整数n,m
输出描述:
一行一个整数表示输出结果一行一个整数表示输出结果一行一个整数表示输出结果
备注:
1≤n,m≤1e6
![](https://img2020.cnblogs.com/blog/1914163/202101/1914163-20210124181410736-822516839.png)
这个就是枚举每一个d,有可能成为gcd的值看看有几个
#include<iostream> #include<algorithm> using namespace std; typedef long long ll; const int maxn=1e6+100; const int mod=1e9+7; /* [gcd(i,j)^2] i属于1到n j属于1到m */ ll f[maxn]; int main(){ ll n,m; cin>>n>>m; ll res=0; for(int i=min(n,m);i>=1;i--){ f[i]=(n/i)*(m/i); for(int j=i*2;j<=min(n,m);j+=i){ f[i]-=f[j]; } res=(res+f[i]*i%mod*i%mod)%mod;//gcd为i的有f[i]个 } cout<<res<<endl; }