zoukankan      html  css  js  c++  java
  • [BZOJ1101][POI2007]Zap 莫比乌斯反演

    1101: [POI2007]Zap

    Time Limit: 10 Sec  Memory Limit: 162 MB
    Submit: 2796  Solved: 1201
    [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)。

    HINT

     

    Source

    要求gcd(x,y)=d只要求 ∑(1≤x≤a/d)∑(1≤y≤b/d)[gcd(x,y)=1]

    由于莫比乌斯函数性质∑(k|n)µ(k)只有当n等于1时函数值为1,其余函数值为0。

    所以可以转换为求∑(1≤x≤a/d)∑(1≤y≤b/d)∑(k|gcd(x,y))µ(k)

    把k提到第一位枚举后可化为∑(1≤k≤min(a/d,b/d))∑(k|x)∑(k|y) µ(k)

    合并后两位可化为 ∑(1≤k≤min(a/d,b/d)) µ(k)*(a/d/k)*(b/d/k)

    按(a/d/k)*(b/d/k)分组即可o(√n) 查询

     1 #include<iostream>
     2 #include<cstring>
     3 #include<cstdlib>
     4 #include<cmath>
     5 #include<cstdio>
     6 #include<algorithm>
     7 #define maxn 50005
     8 #define LL long long
     9 using namespace std;
    10 bool vis[maxn];
    11 int prime[maxn],cnt,u[maxn],sum[maxn];
    12 void init() {
    13     u[1]=sum[1]=1;
    14     for(int i=2;i<maxn;i++) {
    15         if(!vis[i]) prime[++cnt]=i,u[i]=-1; 
    16         for(int j=1;i*prime[j]<maxn&&j<=cnt;j++) {
    17             vis[i*prime[j]]=1;
    18             if(i%prime[j]==0) {u[i*prime[j]]=0;break;}
    19             u[i*prime[j]]=-u[i];
    20         }
    21         sum[i]=sum[i-1]+u[i];
    22     }
    23     return ;
    24 }
    25 int a,b,c,d,k,t;
    26 LL f(int n,int m,int k) {
    27     LL ans=0;
    28     n/=k;m/=k;
    29     for(int i=1,lst;i<=min(n,m);i=lst+1) {
    30         lst=min(n/(n/i),m/(m/i));
    31         ans+=(LL)(n/i)*(m/i)*(sum[lst]-sum[i-1]);
    32     }
    33     return ans;
    34 }
    35 int main() {
    36     init();
    37     scanf("%d",&t);
    38     while(t--) {
    39         scanf("%d%d%d",&a,&b,&k);
    40         printf("%lld
    ",f(a,b,k));
    41     }
    42 }
    View Code
    O(∩_∩)O~ (*^__^*) 嘻嘻…… O(∩_∩)O哈哈~
  • 相关阅读:
    Android Zygote介绍
    Android binder介绍(下)
    Android binder介绍(上)
    Android init介绍(下)
    Android init介绍(上)
    Android 网络服务介绍
    Linux代理服务器使用
    Linux ALSA介绍
    ZigBee MAC层(下)
    ZigBee MAC层(上)
  • 原文地址:https://www.cnblogs.com/wls001/p/8029166.html
Copyright © 2011-2022 走看看