BZOJ 2005: [Noi2010]能量采集(容斥+数论)

传送门

解题思路

  首先题目要求的其实就是\(\sum\limits_{i=1}^n \sum\limits_{j=1}^m [(gcd(i,j)-1)*2+1)]\),然后变形可得\(-n*m+2\sum\limits_{i=1}^n \sum\limits_{j=1}^m gcd(i,j)\)。所以本质上是求后面那个式子,设\(f[i]\)表示\(i\)这个约数作为\(gcd\)的次数,然后转移时考虑容斥,\(n/i*m/i\)表示含有\(i\)这个约数的数字个数,再减去\(f[i*2],f[i*3]...\)这些\(gcd\)不为\(i\)的。

代码

#include<iostream>
#include<cstdio>
#include<cstring>

using namespace std;
const int MAXN = 100005;
typedef long long LL;

LL f[MAXN],ans;
int n,m;

int main(){
    scanf("%d%d",&n,&m);if(n>m) swap(n,m);
    for(int i=n;i;i--){
        f[i]=(LL)(n/i)*(m/i);
        for(int j=(i<<1);j<=n;j+=i)
            f[i]-=f[j];
        ans+=f[i]*i;
    }
    printf("%lld",ans*2-(LL)n*m);
    return 0;
} 
posted @ 2018-12-10 23:09  Monster_Qi  阅读(...)  评论(...编辑  收藏