您的位置:首页 > 编程语言 > Go语言

HDU 4983/BC 6C Goffi and GCD

2015-08-01 14:38 495 查看
题面大意:给定n,k 求 使 gcd(n-a,n) gcd(n-b,n)=n^k 成立的a,b的组合数(1<=a,b<=n)

首先当k大于2时 只有n=1 是 结果为1 其他为0

当k等于2时 结果为1

关键在于k=1时

原式可简化为 gcd(a,n) gcd(b,n)=n (0<=a,b<n) (由于gcd(0,n)=gcd(n,n)=n) 所以可改为(1<=a,b<=n)

而gcd(a,n) 和gcd(b,n)一个分别为n的2个因子,所以就需要我们枚举n的因子,值得注意的是,a是不一定等于gcd(a,n)的, a可以 为gcd(a,n)*与n互质的数,这样gcd(a,n)依然不变,而且,比如n 分解质因数包含3个2 如果gcd(a,n)也包含3个2 ,那a还是可以是gcd(a,n) 乘若干个2,所以 终上所述,a可以是gcd(a,n)*(与n/a互质的数),而与n/a互质的数

,可以通过欧拉函数来求。而n的因子的处理,可以先筛素数,在分解质因数,在dfs跑出来,我是直接在分解质因数时,直接处理出来了。

#include <iostream>
#include <cstring>
#include <string>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <vector>
#include <queue>
#include <map>
#include<stack>
#include<bitset>
#define inf 0x3f3f3f3f
#define ll long long
using namespace std;
#define bug puts("bugbugubgbugbug");
const int mod=1000000007;
vector<ll>vec;
bool visit[100005]= {0};
ll prime[100005]= {0};
map<int,int>mp;
int init_prim(int n)
{
    memset(visit, true, sizeof(visit));
    int num = 0;
    for (int i = 2; i <= n; ++i)
    {
        if (visit[i] == true)
        {
            num++;
            prime[num] = i;
        }
        for (int j = 1; ((j <= num) && (i * prime[j] <= n));  ++j)
        {
            visit[i * prime[j]] = false;
            if (i % prime[j] == 0) break; //点睛之笔
        }
    }
    return num;//返回质数
}
ll go(ll x)
{
    ll res = x;
    ll xx=x;
    for (ll i = 2; i <= x / i; i++) if (x % i == 0)
        {
            res = res / i * (i - 1);
            while(x % i == 0) x /= i;
        }
    if (x > 1) res = res / x * (x - 1);
    return res;
}
int main()
{
    ll n,k;
    int nump=init_prim(100000);
    while(~scanf("%lld%lld",&n,&k))
    {
        vec.clear();
        mp.clear();
        ll nn=n;
        if(n==1)
        {
            printf("1\n");
            continue;
        }
        if(k>2)
        {
            printf("0\n");
            continue;
        }
        if(k==2)
        {
            printf("1\n");
            continue;
        }
        for(ll i=1; i<nump&&n!=1; i++)
            if(n%prime[i]==0)
            {
                ll l=vec.size();
                ll cc=1;
                while(n%prime[i]==0&&n!=1)
                {
                    n/=prime[i];
                    cc*=prime[i];
                    if(mp[cc]++==0)
                    vec.push_back(cc);
                    for(ll j=0; j<l; j++)
                        if(mp[vec[j]*cc]++==0)
                        vec.push_back(vec[j]*cc);
                }
            }
            if(n!=1){
                int l=vec.size();
                for(int i=0;i<l;i++)
                {
                    vec.push_back(vec[i]*n);
                }
            vec.push_back(n);
            }
        vec.push_back(1);
        ll ans=0;
        for(ll i=0; i<vec.size(); i++)
        {
        //    cout<<vec[i]<< " "<<go(vec[i])<<endl;
            ans=(ans+go(vec[i])*go(nn/vec[i])%mod)%mod;
        }
        printf("%lld\n",ans);
    }
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: