P1447【能量采集】

能量采集

题目

P1447


解析

提取题意:求 ∑ i = 1 n ∑ j = 1 m 2 ∗ g c d ( i , j ) + 1 \sum_{i=1}^{n}\sum_{j=1}^{m}2*gcd(i,j)+1 ∑i=1n​∑j=1m​2∗gcd(i,j)+1
提取常数项得 n ∗ m + 2 ∗ ∑ i = 1 n ∑ j = 1 m g c d ( i , j ) n*m+2*\sum_{i=1}^{n}\sum_{j=1}^{m}gcd(i,j) n∗m+2∗∑i=1n​∑j=1m​gcd(i,j)
不妨设n<=m,考虑利用欧拉函数的性质: ∑ d ∣ n ϕ ( d ) = n \sum_{d\mid n}\phi(d)=n ∑d∣n​ϕ(d)=n
把性质套进去得
∑ i = 1 n ∑ j = 1 m ∑ d ∣ i , d ∣ j ϕ ( d ) \sum_{i=1}^{n}\sum_{j=1}^{m}\sum_{d\mid i,d\mid j}\phi(d) i=1∑n​j=1∑m​d∣i,d∣j∑​ϕ(d)
倍数法优化得
∑ i = 1 n ϕ ( i ) ∗ ⌊ n d ⌋ ∗ ⌊ m d ⌋ \sum_{i=1}^{n}\phi(i)*⌊\frac{n}{d}⌋*⌊\frac{m}{d}⌋ i=1∑n​ϕ(i)∗⌊dn​⌋∗⌊dm​⌋
O ( n ) O(n) O(n)预处理欧拉函数,再套整除分块 O ( n ) O(\sqrt n) O(n ​),这个题目就 O ( m i n ( n , m ) ) O(min(n,m)) O(min(n,m))的解决了
PS:似乎可以用杜教筛的方式提高效率
本题有莫比乌斯反演 O ( m i n ( n , m ) ) O(min(n,m)) O(min(n,m))/容斥 O ( n log ⁡ n ) ? O ( n log ⁡ log ⁡ n ) ? O(n\log n)?O(n\log \log n)? O(nlogn)?O(nloglogn)?的做法,此处省略

code:

#include<cstdio>
#define rr register int
#define int long long
using namespace std;
inline int min(int x,int y){return x<y?x:y;}
int n,m,ans,phi[100010],pr[100010],tot;
bool vis[100010];
signed main()
{
	scanf("%lld%lld",&n,&m),phi[1]=1;
	if(n>m)n^=m^=n^=m;
	for(rr i=2;i<=n;++i)
	{
		if(!vis[i])pr[++tot]=i,phi[i]=i-1;
		for(rr j=1;j<=tot&&pr[j]*i<=n;++j)
		{
			vis[pr[j]*i]=1;
			if(!(i%pr[j])){phi[i*pr[j]]=phi[i]*pr[j];break;}
			phi[i*pr[j]]=(pr[j]-1)*phi[i];
		}
	}
	for(rr i=2;i<=n;++i)phi[i]+=phi[i-1];
	for(rr l=1,r;l<=n;l=r+1)ans+=(phi[r=min(n/(n/l),m/(m/l))]-phi[l-1])*(n/l)*(m/l);
	printf("%lld",(ans<<1)-n*m);
	return 0;
}
上一篇:势能分析


下一篇:最优传输算法——Benamou Brenier算法