洛谷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)个矩阵。那么答案就是Σn==i+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;
}

猜你喜欢

转载自www.cnblogs.com/BLUE-EYE/p/9574840.html