题目链接:https://codeforces.com/gym/101982/attachments

贴一张图吧:

题目意思就是给出四个数字,a,b,c,d,分别代表两个区间[a,b],[c,d],从这两个区间里面分别拿一个数字组成(x,y),问x和y互质的组合有多少种。

这道题目好像要用莫比乌斯反演,但是目前没有了解过这个知识点,后续会补上,我用的是打表+容斥定理做的,相比于上一种方法,耗费的时间可能会多很多。我亲测是600到800ms,所以还是很有必要学莫比乌斯反演的。

接下来讲我的思路:两个区间里面所有的组合数是(b-a+1)*(d-c+1)种,我可以先算出不互质的组合的个数,再用总数减去它得到互质的组合数。

首先,假设我要算所有gcd(x,y)=2的组合数,那么在区间[a,b]里面,素因子含有2的数字个数是b/2-(a-1)/2这么多个,在区间[c,d]里面含有2这个素因子的数字的个数是d/2-(c-1)/2这么多。这两个数字相乘就是两个区间中gcd(x,y)=2的组合数字。

假如我们遍历计算1到10000000里面所有的素数(大概660000多一点),那么就会出现重复计算的情况,假如我gcd(x,y)=2和gcd(x,y)=3的情况都计算了一边,那么gcd(x,y)=6的情况就计算了两遍,那么我们就要再减去gcd(x,y)=6的情况的组合数。

这就要用到容斥定理(奇加偶减),假如一个数字n,它不同的素因子有奇数个,那么就加,如果是偶数个就减,并且它某一个素因子个数不能大于1个(6=2*3,它的素因子有2和3,素因子2有且只有一个,素因子3有且只有一个,那么这个数字我们是要计算的,另一个数字12=2*2*3,它的素因子2有2个,那么我们就不用计算它,因为它已经包含在(gcd(x,y)=2)的数量+(gcd(x,y)=3)的数量-(gcd(x,y)=6)里面了)。

那么我们现在就要先打表把所有类似于6(2*3),10(2*5),30(2*3*5),这种相同素因子只有一个的数筛出来(大概6000000个,所以花费时间有点多),然后遍历计算就可以了。

这个打表的过程可以在我们线性筛素数的过程中做到,所以这个打表是线性的。

这里面num[i]代表数字i有多少个不同的素数,例如num[30]=3,(30=2*3*5)。

flag[i]表示数字i是不是所有素数有且只有一个,如果flag[i]=true,那么这个i就是我们要找的数字。数组ok就是把这些数字存起来,等下遍历数组ok就可以了。

打表代码:

  1. void init(){
  2. memset(vis,,sizeof(vis));
  3. memset(flag,false,sizeof(flag));
  4. cnt=;//记录素数个数
  5. cc=;//计录我们要找的数组个数
  6. for(int i=;i<maxn;i++){
  7. if(vis[i]==){
  8. prime[cnt++]=i;//是一个素数
  9. num[i]=; //不同的素因子是有它自己一个,复制为1
  10. ok[cc++]=i; //保存在ok数组中
  11. flag[i]=true; //标记这个数字是我们要找的
  12. }
  13. for(int j=;j<cnt&&(i*prime[j]<maxn);j++){
  14. vis[prime[j]*i]=true;
  15. if((i%prime[j])!=)//在这之前我们已经知道了num[i],只要i不被prime[j]整除,那么prime[j]*i这个数字不同素因子个数就是num[i]+1
  16. num[prime[j]*i]=num[i]+;
  17. if(flag[i]==&&(i%prime[j])){//假如flag[i]=true,说明i是我们要找的数字,并且i%prime[j]非0,那么prime[j]*i也是我们要找的数字
  18. ok[cc++]=i*prime[j];
  19. flag[i*prime[j]]=true;
  20. }
  21. if(i%prime[j]==)
  22. break;
  23. }
  24. }
  25. }

完整代码:

  1. #include<iostream>
  2. #include<cstring>
  3. #include<algorithm>
  4. #include<queue>
  5. #include<map>
  6. #include<stack>
  7. #include<cmath>
  8. #include<vector>
  9. #include<set>
  10. #include<cstdio>
  11. #include<string>
  12. #include<deque>
  13. using namespace std;
  14. typedef long long LL;
  15. #define eps 1e-8
  16. #define INF 0x3f3f3f3f
  17. #define maxn 10000005
  18. int prime[maxn],vis[maxn],num[maxn],ok[maxn],flag[maxn];
  19. int n,m,k,t,cnt,cc;
  20. void init(){
  21. memset(vis,,sizeof(vis));
  22. memset(flag,false,sizeof(flag));
  23. cnt=;//记录素数个数
  24. cc=;//计录我们要找的数组个数
  25. for(int i=;i<maxn;i++){
  26. if(vis[i]==){
  27. prime[cnt++]=i;//是一个素数
  28. num[i]=; //不同的素因子是有它自己一个,复制为1
  29. ok[cc++]=i; //保存在ok数组中
  30. flag[i]=true; //标记这个数字是我们要找的
  31. }
  32. for(int j=;j<cnt&&(i*prime[j]<maxn);j++){
  33. vis[prime[j]*i]=true;
  34. if((i%prime[j])!=)//在这之前我们已经知道了num[i],只要i不被prime[j]整除,那么prime[j]*i这个数字不同素因子个数就是num[i]+1
  35. num[prime[j]*i]=num[i]+;
  36. if(flag[i]==&&(i%prime[j])){//假如flag[i]=true,说明i是我们要找的数字,并且i%prime[j]非0,那么prime[j]*i也是我们要找的数字
  37. ok[cc++]=i*prime[j];
  38. flag[i*prime[j]]=true;
  39. }
  40. if(i%prime[j]==)
  41. break;
  42. }
  43. }
  44. }
  45. int main()
  46. {
  47. int a,b,c,d;
  48. init();
  49. sort(ok,ok+cc);
  50. while(scanf("%d%d%d%d",&a,&b,&c,&d)!=EOF){
  51. LL ans=;
  52. int maxx=min(b,d);//记录一下两个,区间最小的右边界,可有可无吧 ,好像影响不大
  53. for(int i=;i<cc&&ok[i]<=maxx;i++){
  54. int now=ok[i];
  55. if(num[now]%){//计数加 ,注意答案非常大,要用long long
  56. ans+=(LL)(b/now-(a-)/now)*(d/now-(c-)/now);
  57. }else{//偶数减
  58. ans-=(LL)(b/now-(a-)/now)*(d/now-(c-)/now);
  59. }
  60. }
  61. printf("%lld\n",(LL)(b-a+)*(d-c+)-ans);
  62. }
  63. return ;
  64. }

待补充。。。。。。

来补充了,额,请看下面大佬介绍莫比乌斯反演,完......

补充:https://www.cnblogs.com/chenyang920/p/4811995.html

gym 101982 B题 Coprime Integers的更多相关文章

  1. Gym - 101982B Coprime Integers (莫比乌斯反演)

    题目链接:http://codeforces.com/gym/101982/attachments 题目大意:有区间[a,b]和区间[c,d],求gcd(x,y)=1,其中x属于[a,b],y属于[c ...

  2. Gym - 101982B 2018-2019 ACM-ICPC Pacific Northwest Regional Contest (Div. 1) B. Coprime Integers Mobius+容斥 ab间gcd(x,y)=1的对数

    题面 题意:给你 abcd(1e7),求a<=x<=b,c<=y<=d的,gcd(x,y)=1的数量 题解:经典题目,求从1的到n中选x,从1到m中选y的,gcd(x,y)=k ...

  3. 莫比乌斯反演第二弹 入门 Coprime Integers Gym - 101982B

    题目链接:https://cn.vjudge.net/problem/Gym-101982B 题目大意: 给你(a,b)和(c,d)这两个区间,然后问你这两个区间中互素的对数是多少. 具体思路:和我上 ...

  4. Gym - 100221D 一题一直没过的dfs,,应该是纯手动码?

    不写了,10年以后再回来写. http://codeforces.com/gym/100221/attachments H题

  5. codeforces GYM 100971F 公式题或者三分

    F. Two Points time limit per test 2 seconds memory limit per test 256 megabytes input standard input ...

  6. Gym - 100676E —— 基础题

    题目链接:https://odzkskevi.qnssl.com/1110bec98ca57b5ce6aec79b210d2849?v=1490453767 题解: 这种方法大概跟离散化扯上点关系:首 ...

  7. Gym - 101982F Rectangles (扫描线+线段树)

    链接:http://codeforces.com/gym/101982/attachments 思路: 问被覆盖次数为奇数次的矩阵的面积并 扫描线求矩阵面积并我们是上界赋为-1,下界赋为1,因为要求覆 ...

  8. codeforces Gym 100735 D、E、G、H、I

    http://codeforces.com/gym/100735 D题 直接暴力枚举 感觉这道题数据有点问题 为什么要先排下序才能过?不懂.. #include <stdio.h> #in ...

  9. Gym - 101982F 扫描线+线段树

    题目链接:https://codeforces.com/gym/101982/attachments 要你求覆盖奇数次的矩形面积并,每次更新时减去原先的值即可实现奇数次有效,下推时为保证线段长度不变左 ...

随机推荐

  1. 如何破解QQ空间相册密码访问权限2019方法

    今天小编给大家介绍一下最新的QQ空间相册破解方法,是2019年最新方法,本方法来自互联网,下面开始方法教程 教程之前我们需要下载软件,地址我发在下方 软件切图 1.首先我们打开软件,然后在“操作界面” ...

  2. VS2017 ASP.NET MVC 5.0 开部署问题汇总

    1[SqlException (0x80131904): 拒绝了对对象 '****' (数据库 '***',架构 'dbo')的 EXECUTE 权限.] “/”应用程序中的服务器错误. SQL 20 ...

  3. Python全栈开发记录_第四篇(集合、函数等知识点)

    知识点1:深拷贝和浅拷贝 非拷贝(=赋值:数据完全共享,内存地址一样,修改一个另一个也变化) 浅拷贝:数据半共享(复制其数据独立内存存放,但是只拷贝成功第一层)像[[1,2],3,4]如果修改列表中列 ...

  4. linux下导入、导出mysql数据库命令的实现方法

    首先建空数据库 mysql>create database abc; 导入数据库 mysql>use abc; 设置数据库编码 mysql>set names utf8; 导入数据( ...

  5. springboot学习随笔(四):Springboot整合mybatis(含generator自动生成代码)

    这章我们将通过springboot整合mybatis来操作数据库 以下内容分为两部分,一部分主要介绍generator自动生成代码,生成model.dao层接口.dao接口对应的sql配置文件 第一部 ...

  6. WEB日志分析工具(Webslizer和AWstats)

    https://www.cnblogs.com/xiaowenshu/p/10030139.html#top

  7. Java JTable列顺序和列宽度保存在用户本地

    上周碰到了一个棘手的需求,就是要把用JTable的列顺序和列宽度保存下来,这次用户调整了列宽度,关闭程序,下次再打开时,这个列的宽还是要保持,因为SWing的特性,都是在程序启动时就确定了列顺序和列宽 ...

  8. C#对象与XMl文件之间的相互转换(转)

    本文是对C#中对象与XMl文件之间的相互转换进行了详细的介绍,需要的朋友可以过来参考下,希望对大家有所帮助 C#提供三种序列化方式,分别为:1.是使用BinaryFormatter进行串行化: 2.使 ...

  9. Windows下查看自己电脑的网关mac以及手动获取新的地址

    场景:正在上班时,工作电脑突然无法连接网络了.查看配置发现DNS服务器地址被分配到了192.168.1.1,瞬间懵了? 过程:(1)进入cmd.使用ipconfig /all查看网关地址; (2)使用 ...

  10. java将错误信息写入文件

    第一种办法可以通过字符串,也就是先把错误信息写入字符串,再将字符串写入文件 import java.io.*; public class Demo { public static void main( ...