zoukankan      html  css  js  c++  java
  • 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 ]

    1. 对于一个x,使得(gcd(x,m)=g),当存在一个(gcd(a[i],m)|g)时,则这个x就会被计入答案。
      那么就可以枚举(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} ]

    1. 枚举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;
    }
    
    
  • 相关阅读:
    StringTokenizer类的使用
    ResultSet相关ResultSetMetaData详细
    jdbcTemplate 获取数据表结构
    关于数组和List之间相互转换的方法
    cat ,more, Less区别
    落地数据和不落地数据
    eclipse代码格式化
    如何修改word的项目编号
    .Net配置文件——反射+配置文件存储类型实例
    unix mkdir命令的使用方法
  • 原文地址:https://www.cnblogs.com/RRRR-wys/p/9689624.html
Copyright © 2011-2022 走看看