zoukankan      html  css  js  c++  java
  • [POI2007]Zap

    bzoj 1101: [POI2007]Zap

    Time Limit: 10 Sec  Memory Limit: 162 MB
    [Submit][Status][Discuss]

    Description

      FGD正在破解一段密码,他需要回答很多类似的问题:对于给定的整数a,b和d,有多少正整数对x,y,满足x<=a
    ,y<=b,并且gcd(x,y)=d。作为FGD的同学,FGD希望得到你的帮助。

    Input

      第一行包含一个正整数n,表示一共有n组询问。(1<=n<= 50000)接下来n行,每行表示一个询问,每行三个
    正整数,分别为a,b,d。(1<=d<=a,b<=50000)

    Output

      对于每组询问,输出到输出文件zap.out一个正整数,表示满足条件的整数对数。

    Sample Input

    2
    4 5 2
    6 4 3

    Sample Output

    3
    2
    //对于第一组询问,满足条件的整数对有(2,2),(2,4),(4,2)。对于第二组询问,满足条件的整数对有(
    6,3),(3,3)。
     

    gcd(x/d,y/d)=1
       

        a b

        Σ Σ gcd(x,y)=d 

        x y

        

        a/d  b/d

    =   Σ     Σ   gcd(x’ ,y’)=1

         x’     y’

        a/d  b/d

    =   Σ    Σ    Σ  μ(d’)

         x’    y’    d’gcd(x’ ,y’)

       

       min(x’,y’)   a/dd’   b/dd’

    =    Σ                 Σ         Σ      μ(d’)

          d’                x’’         y’’

     min(x’,y’)

    =  Σ            μ(d’) floor(a/dd’) floor(b/dd’)

        d’           

    #include<cstdio>
    #include<algorithm>
    #define N 50001
    using namespace std;
    int t,a,b,d;
    int prime[N],cnt,mul[N],sum[N];
    bool v[N];
    void mobius()
    {
        mul[1]=1;
        for(int i=2;i<N;i++)
        {
            if(!v[i])
            {
                v[i]=true;
                prime[++cnt]=i;
                mul[i]=-1;
            }
            for(int j=1;j<=cnt;j++)
            {
                if(prime[j]*i>N-1) break;
                v[prime[j]*i]=true;
                if(i%prime[j]==0)
                {
                    mul[i*prime[j]]=0;
                    break;
                }
                else mul[i*prime[j]]=-mul[i];
            }
        }
    }
    void solve()
    {
        a/=d;b/=d;
        int k=min(a,b),j,ans=0;
        for(int i=1;i<=k;i=j+1)
        {
            j=min(a/(a/i),b/(b/i));
            ans+=(a/i)*(b/i)*(sum[j]-sum[i-1]);
        }
        printf("%d
    ",ans);
    }
    int main()
    {
        scanf("%d",&t);
        mobius();
        for(int i=1;i<N;i++) sum[i]=sum[i-1]+mul[i];
        while(t--)
        {
            scanf("%d%d%d",&a,&b,&d);
            solve();
        }
    }
  • 相关阅读:
    hdu4549(费马小定理 + 快速幂)
    java 四种实现延迟加载的方法
    浅谈java缓存
    JavaWeb实现文件上传下载功能实例解析
    java分页之页面分页
    浅析Java开发模式—Model1、Model2和三层
    构建一个简单的基于MVC模式的JavaWeb
    Java中MVC详解以及优缺点总结
    Servlet
    通过JDBC进行简单的增删改查(以MySQL为例)
  • 原文地址:https://www.cnblogs.com/TheRoadToTheGold/p/6609495.html
Copyright © 2011-2022 走看看