HDU - 5514 Frogs

题目大意:有n只青蛙,每只青蛙的弹跳能力为ai,他们都从0出发,绕着m个石头围成的圈子跳跃,石头编号为0~m-1,问能被跳到的石头编号之和

具体思路:首先可以发现弹跳能力为ai的青蛙,可以跳到的石头编号是gcd(ai, m)的倍数

枚举m的因子,若某个青蛙可以弹跳的石头编号中有该因子,那证明编号为这个因子的石头一定会被跳到

num[i]记录编号为i的石头被跳了几次,如果被跳的次数不等于应跳的次数(不为0或1),则减去多余的影响

AC代码

#include<bits/stdc++.h>
#define int long long
using namespace std;
int T,i,j,n,m,vis[100000],num[100000],x,t;
int gcd(int a,int b)
{
    if(b==0)return a;
    else return gcd(b,a%b);
}
map <int,int> mp;
vector <int> d;
main()
{
    scanf("%lld",&T);
    for (int tt=1; tt<=T; tt++)
    {
        scanf("%lld%lld",&n,&m);
        int M=(int)sqrt(m);
        for (i=1; i<=M; i++)
        {
            if(m%i==0)
            {
                d.push_back(i);
                if(m/i!=i)d.push_back(m/i);
            }
        }
        sort(d.begin(),d.end());
        memset(vis,0,sizeof vis);
        memset(num,0,sizeof num);
        for(i = 1; i <= n; ++i)
        {
            scanf("%lld",&x);
            t=gcd(x,m);
            M=d.size();
            for(j=0; j<M; ++j)if(d[j]%t==0)vis[j]=1;
        }
        int ans=0;
        M=d.size()-1;
        for(i = 0; i<M; ++i)
            if(vis[i]!=num[i])
            {
                t=(m-1)/d[i];
                ans+=t*(t+1)/2*d[i]*(vis[i]-num[i]);
                t=vis[i]-num[i];
                for(j = i; j <M; ++j)
                    if(d[j]%d[i]==0)num[j]+=t;
            }
        printf("Case #%lld: %lld\n",tt,ans);
    }
    return 0;
}

 

posted @ 2017-11-01 16:10  橙子用户  阅读(112)  评论(0编辑  收藏  举报