洛谷4388 付公主的矩形(数论,数学)

好题!!!
我比较菜,没有推出来,还是看了别人的题解。对于一个nm的矩阵且gcd(n,m)==1,从1,1到(n,m)肯定只穿过了n+m-1个矩阵,因为中间没有经过整点。同时,对于任意n,m经过的矩阵就相当于q=n/gcd(n,m),w=m/gcd(n,m),那么对于qw的矩阵,穿过了q+w-1个矩阵,那么对于nm的矩阵,经过了(q+w-1)gcd(n,m)个矩阵,那么就相当于n*m的矩阵经过了n+m-gcd(n,m)个矩阵。那么答案就是Σni+j-gcd(i,j)。由于这玩意的复杂度很高,到了n²lnn,一分都骗不到,我们考虑优化。记N=i+j-gcd(i,j),d=gcd(i,j),将左边的式子两边除以d,假设得到的式子是N'=i'+j'-1。所以gcd(i',j')gcd(i',N'+1-j')gcd(i',N'+1)1,那么对于这个N'来说,所得答案就是φ(N'+1),那么答案就是Σ(d|n)φ(d+1);

#include <cstdio>
#include <cstring>
using namespace std;

const int N = 1e6 + 5;

int n, l = 0, ans = 0, pri[N], phi[N];
bool np[N];

inline void sieve() {
	phi[1]=0;
	for(int i=2;i<=n+1;i++){
		if(!np[i]) np[i]=1,phi[i]=i-1,pri[++l]=i;
		for(int j=1;i*pri[j]<=n+1;j++){
			np[i*pri[j]]=1;
			if(i%pri[j]==0){phi[i*pri[j]]=phi[i]*pri[j];break;}
			phi[i*pri[j]]=phi[i]*phi[pri[j]];
		}
	} 
} 
int main() {
	scanf("%d", &n);
	sieve();
	for(int i = 1; i <= n; i++)
		if(n % i == 0) ans += phi[i + 1];
	printf("%d\n", (ans + 1) / 2);
	return 0;
}
posted @ 2018-09-02 19:09  BLUE_EYE  阅读(183)  评论(0编辑  收藏  举报