bzoj1101: [POI2007]Zap(莫比乌斯反演)

原题链接

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

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

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

输入样例
2
4 5 2
6 4

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

解析:挺裸的莫比乌斯反演题。
   设\(f(x)=gcd为x的(x,y)的对数\)
   设\(F(x)=gcd为x或x的倍数的(x,y)的对数\)
   那么显然\(F(x)=\sum_{x|d}f(d)\)
   所以\(f(x)=\sum_{x|d}μ(⌊\frac{d}{x}⌋)F(d)\)
   而\(F(x)=⌊\frac{n}{x}⌋⌊\frac{m}{x}⌋\)
   可得\(f(x)=\sum_{x|d}μ(⌊\frac{d}{x}⌋)⌊\frac{n}{d}⌋⌊\frac{m}{d}⌋\)
   枚举\(⌊\frac{d}{x}⌋\),则\(f(x)=\sum_{i=1}^{min(⌊\frac{n}{x}⌋,⌊\frac{m}{x}⌋)}μ(i)⌊\frac{n}{ix}⌋⌊\frac{m}{ix}⌋\)
   这时就可以用整除分块计算了

代码如下:

#include<cstdio>
#include<algorithm>
#define ll long long
using namespace std;

const int maxn = 5e4 + 5;
int n, mu[maxn], primi[maxn], tot, mark[maxn], k, prim[maxn];
ll sum[maxn], ans;

int read(void) {
    char c; while (c = getchar(), c < '0' || c >'9'); int x = c - '0';
    while (c = getchar(), c >= '0' && c <= '9') x = x * 10 + c - '0'; return x;
}

void get_mu(void) { //筛mu函数 
    mu[1] = 1; mark[1] = 1;
    int lim = maxn - 5;
      for (int i = 2; i <= lim; ++ i) {
        if (!mark[i]) mu[i] = -1, prim[++ tot] = i;
        for (int j = 1; j <= tot && prim[j] * i <= lim; ++ j) {
            mark[prim[j] * i] = 1;
            if (i % prim[j] == 0) break;
              else mu[prim[j] * i] = -mu[i];
          }
      } 
      for (int i = 1; i <= lim; ++ i) sum[i] = sum[i - 1] + mu[i]; //维护mu函数的前缀和 
}

int main() {
    get_mu();
    n = read();
      while (n --) {
        int a = read(), b = read(), d = read();
        a /= d; b /= d; ans = 0;
        int lim = min(a, b); //整数分块计算 
          for (int l = 1, r; l <= lim; l = r + 1) {
              r = min(a / (a / l), b / (b / l));
              ans += (sum[r] - sum[l - 1]) * (a / l) *(b / l);
            }
        printf("%lld\n", ans);
      }
    return 0;
} 

转载于:https://www.cnblogs.com/Gaxc/p/10088151.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
牙科就诊管理系统利用当下成熟完善的SSM框架,使用跨平台的可开发大型商业网站的Java语言,以及最受欢迎的RDBMS应用软件之一的Mysql数据库进行程序开发。实现了用户在线查看数据。管理员管理病例管理、字典管理、公告管理、药单管理、药品管理、药品收藏管理、药品评价管理、药品订单管理、牙医管理、牙医收藏管理、牙医评价管理、牙医挂号管理、用户管理、管理员管理等功能。牙科就诊管理系统的开发根据操作人员需要设计的界面简洁美观,在功能模块布局上跟同类型网站保持一致,程序在实现基本要求功能时,也为数据信息面临的安全问题提供了一些实用的解决方案。可以说该程序在帮助管理者高效率地处理工作事务的同时,也实现了数据信息的整体化,规范化与自动化。 管理员在后台主要管理病例管理、字典管理、公告管理、药单管理、药品管理、药品收藏管理、药品评价管理、药品订单管理、牙医管理、牙医收藏管理、牙医评价管理、牙医挂号管理、用户管理、管理员管理等。 牙医列表页面,此页面提供给管理员的功能有:查看牙医、新增牙医、修改牙医、删除牙医等。公告信息管理页面提供的功能操作有:新增公告,修改公告,删除公告操作。公告类型管理页面显示所有公告类型,在此页面既可以让管理员添加新的公告信息类型,也能对已有的公告类型信息执行编辑更新,失效的公告类型信息也能让管理员快速删除。药品管理页面,此页面提供给管理员的功能有:新增药品,修改药品,删除药品。药品类型管理页面,此页面提供给管理员的功能有:新增药品类型,修改药品类型,删除药品类型。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值