triple

来源:互联网 发布:mac 加速器 编辑:程序博客网 时间:2024/05/01 08:53
Description
给出一个整数n,表示1,2,...,n。从这n个数中任意选择3个不同的数字x,y,z,问x,y,z的最大公约数等于m的方案有多少种?(注意:(1,2,3),(1,3,2),(2,1,3),(2,3,1),(3,1,2),(3,2,1)属于同一种方案)
Input
第一行输入一个整数T(1 <= T <= 100),表示有T组数据,
接下来T行,每行2个整数n, m(1 <= m <= n <= 10^5)
Output
输出一个整数表示答案
Sample Input
1
5 1
Sample Output

10

gcd为k,那么三个数都是k的倍数;

把倍数容斥掉就好了;

用莫比乌斯反演一下。

#include <iostream>#include<cstdio>#include<cstring>#define ll long longusing namespace std;int mu[100005],vis[100005],prime[100005];int N=100000,cnt;void Init(){    memset(vis,0,sizeof(vis));    mu[1] = 1;    cnt = 0;    for(int i=2; i<N; i++)    {        if(!vis[i])        {            prime[cnt++] = i;            mu[i] = -1;        }        for(int j=0; j<cnt&&i*prime[j]<N; j++)        {            vis[i*prime[j]] = 1;            if(i%prime[j]) mu[i*prime[j]] = -mu[i];            else            {                mu[i*prime[j]] = 0;                break;            }        }    }}ll c(int n){    if(n<=2)        return 0;    ll res=n;    res*=(n-1);    res/=2;    res*=(n-2);    res/=3;    return res;}int main(){    int T;    scanf("%d",&T);    Init();    while(T--)    {        int n,m;        scanf("%d%d",&n,&m);        n/=m;        ll ans=0;        for(int i=1;i<=n;i++)            ans+=mu[i]*c(n/i);        cout<<ans<<endl;       /* for(int i=1;i<=100;i++)            cout<<mu[i]<<" ";*/    }    return 0;}


0 0
原创粉丝点击