HDU5514 Frogs

Posted rrrr-wys

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU5514 Frogs相关的知识,希望对你有一定的参考价值。

HDU5514 Frogs


题意:将([0,m))所有符合(a[i]*t ~mod~ m)的值求和

做法:

  1. (a[i]*t ~mod~ m) 会在 (gcd(a[i],m)) 的倍数出现,因此问题等价与求:
    [ sum_{i=1}^{m-1} [ [(a[1],m)|i] or [(a[2],m)|i] or ... or [(a[n],m)|i] ] i ]
  2. 对于一个i,使得(gcd(i,m)=g),当存在一个(gcd(a[i],m)|g)时,则这个i就会被计入答案。
    那么就可以枚举(g)来计算贡献了
    (gcd(i,m)=g), 则(gcd(i/g,m/g)=1),那么对于一个(g)如果他存在一个(gcd(a[i],m)|g),贡献就是:
    [ sum_{i=1}^{m-1} [gcd(i/g,m/g)=1]i = sum_{i=1}^{m/g} [gcd(i,m/g)=1]i*g ]
    又因为
    [ sum_{i=1}^{n}[gcd(i,n)=1]i = frac{varphi(n)*n}{2} ]
    证明:
    [ sum_{i=1}^{n}[gcd(i,n)=1]i + sum_{i=1}^{n}[gcd(n-i,n)=1](n-i) = sum_{i=1}^n [gcd(i,n)=1]n = nvarphi(n)\sum_{i=1}^{n}[gcd(i,n)=1]i = frac{varphi(n)*n}{2} ]
  3. 枚举m的约数g计算即可
#include <bits/stdc++.h>
typedef long long ll;
const int N = 1e4 + 7;
using namespace std;
int T,n;
ll m,a[N];

//
//gcd(x,m) = g => gcd(x/g,m/g) = 1
//
//FOR : g|m
//    if FOR : gcd(a[i],m)|g
//        ans += {sum [gcd(i/g,m/g) == 1]*i => phi(m/g)*(m/g)/2*g => phi(m/g)*m/2}
//
//hints:
//[gcd(i,n)==1] = [gcd(i,n-i)==1]
//sum [gcd(i,n)==1]*i + sum [gcd(n-i,n)==1]*(n-i) = n*sum [gcd(i,n)==1] = n*phi(n)
//=> sum [gcd(i,n)==1]*i = n*phi(n)/2

ll b[1000007];
int cnt = 0;
int ck(ll g) {
    for(int i=0;i<n;++i) if(g%a[i]==0) return 1;
    return 0;
}
ll phi(ll x) {
    ll t = x;
    for(int i=2;i*i<=x;++i) if(x%i==0) {
        t-=t/i;
        while(x%i==0) x/=i;
    }
    if(x>1)t-=t/x;
    return t;
}
int main() {
    scanf("%d",&T);
    for(int ti=1;ti<=T;++ti) {
        scanf("%d%lld",&n,&m);
        int f = 0;
        for(int i=0;i<n;++i) {
            scanf("%lld",&a[i]);
            a[i] = __gcd(a[i],m);
            if(a[i]==1) f=1;
        }
        if(f) {
            printf("Case #%d: %lld
",ti,(m-1)*m>>1LL);
            continue;
        }
        sort(a,a+n);
        n = unique(a,a+n) - a;

        cnt = 0;
        for(ll i=1;i*i<=m;++i) {
            if(m%i==0) {
                if(i*i == m) b[cnt++] = i;
                else {
                    b[cnt++] = i;
                    if(m/i!=1) b[cnt++] = m/i;
                }
            }
        }

        sort(b,b+cnt);
        cnt = unique(b,b+cnt) - b;

        ll ans = 0;
        for(int i=0;i<cnt;++i) {
            if(b[i]<m&&ck(b[i])) {
                ans+= phi(m/b[i]);
            }
        }
        ans*=m; ans/=2;
        printf("Case #%d: %lld
",ti,ans);
    }
    return 0;
}








以上是关于HDU5514 Frogs的主要内容,如果未能解决你的问题,请参考以下文章

hdu 5514 Frogs(容斥)

hdu 5514Frogs

HDU_5514_Frogs

HDU 5514.Frogs-欧拉函数 or 容斥原理

HDU-5514 Frogs

hdu 5514 Frogs 容斥思想+gcd 银牌题