HDU1695:GCD(容斥原理+欧拉函数+质因数分解)好题
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1695
题目解析:
Given 5 integers: a, b, c, d, k, you're to find x in a...b, y in c...d that GCD(x, y) = k.
题目又说a==c==1,所以就是求[1,b]与[1,d]中gcd等于k的个数,因为若gcd(x,y)==z,那么gcd(x/z,y/z)==1,又因为不是z的倍数的肯定不是,所以不是z的倍数的可以直接去掉,所以只要将b和d除以k,然后就转化成了求两个范围中互质的对数了。即求[1,b/k],与[1,d/k]中互质的数目,让b<d,又因为 (x=5, y=7) and (x=7, y=5) are considered to be the same.
所以先求[1,b/k]中互质的数目,即phi[1]+phi[2]+phi[3].....+phi[b/k](其中phi[i]为i的欧拉函数值),再从区间[b/k+1,d/k]枚举与区间[1,b/k]中互质的数目。其中求与区间[1,b/k]中互质的数目可以通过容斥原理求得与区间[1,b/k]中不互质的数目,相减便可以求得结果。这题折腾了一中午,一直TLE,代码在后面贴了,之后看大神的博客知道了哪里超时的原因,每个数的质因子可以在打表求欧拉函数的时候顺便求出来,一种哈希的思想,这样就不用在枚举的时候每一个数在求一遍他的质因子了,好题!
代码如下:(608ms)
- #include <iostream>
- #include <stdio.h>
- #include <string.h>
- #include <algorithm>
- #include <queue>
- #include <math.h>
- using namespace std;
- typedef __int64 ll;
- ll sum,phi[];
- int cnt[][],f[],a,b,c,d,x;
- void init()
- {
- memset(f,,sizeof(f));
- for(int i=; i<=; i++)
- {
- phi[i]=;
- f[i]=;
- }
- phi[]=;
- for(int i=; i<=; i++)
- {
- if(!phi[i])
- {
- for(ll j=i; j<=; j+=i)
- {
- if(!phi[j]) phi[j]=j;
- phi[j]=phi[j]/i*(i-);
- cnt[j][f[j]++]=i;//算是哈希吧,很精辟啊,这种写法要学习
- }
- }
- phi[i]+=phi[i-];
- }
- }
- ll gcd(ll A,ll B)
- {
- return B==?A:gcd(B,A%B);
- }
- void dfs(ll now,ll num,ll lcm,ll &coun,int key)
- {
- lcm=cnt[key][now]/gcd(cnt[key][now],lcm)*lcm;
- if(num&)
- {
- coun+=b/lcm;
- }
- else
- {
- coun-=b/lcm;
- }
- for(ll i=now+; i<f[key]; i++)
- dfs(i,num+,lcm,coun,key);
- }
- int main()
- {
- int T,K=;
- init();
- scanf("%d",&T);
- while(T--)
- {
- scanf("%d%d%d%d%d",&a,&b,&c,&d,&x);
- if(x == || x > b || x > d)
- {
- printf("Case %d: 0\n",++K);
- continue;
- }
- b/=x;
- d/=x;
- sum=;
- if(b>d) swap(b,d);
- sum+=phi[b];
- for(int i=b+; i<=d; i++)
- {
- ll coun=;
- for(int j=; j<f[i]; j++)
- {
- dfs(j,,cnt[i][j],coun,i);
- }
- sum+=(b-coun);
- }
- printf("Case %d: %I64d\n",++K,sum);
- }
- return ;
- }
TLE的:(TLE了一中午 3000ms++)
- #include <iostream>
- #include <stdio.h>
- #include <string.h>
- #include <algorithm>
- #include <queue>
- #include <math.h>
- using namespace std;
- typedef __int64 ll;
- ll a,b,c,d,x,sum,top,cnt[],we;//********
- int phi[],su[],prime[];
- void init()
- {
- we=;
- prime[we++]=;
- su[]=su[]=;
- su[]=;
- for(int i=; i<; i++)
- if(i%==) su[i]=;
- else su[i]=;
- double t=sqrt(*1.0);
- for(ll i=; i<=t; i++)
- {
- if(su[i])
- {
- for(ll j=i*i; j<; j=j+i)
- {
- su[j]=;
- }
- }
- }
- for(ll i=; i<=; i++)
- {
- if(su[i]) prime[we++]=i;
- }
- memset(phi,,sizeof(phi));
- phi[]=;
- for(ll i=; i<=; i++)
- {
- if(!phi[i])
- {
- for(ll j=i; j<=; j+=i)
- {
- if(!phi[j]) phi[j]=j;
- phi[j]=phi[j]/i*(i-);
- }
- }
- }
- }
- ll gcd(ll A,ll B)
- {
- return B==?A:gcd(B,A%B);
- }
- void dfs(ll now,ll num,ll lcm,ll &coun)
- {
- lcm=cnt[now]/gcd(cnt[now],lcm)*lcm;
- if(num&)
- {
- coun+=b/lcm;
- //printf("hsum======%I64d\n",sum);
- }
- else
- {
- coun-=b/lcm;
- }
- for(ll i=now+; i<top; i++)
- dfs(i,num+,lcm,coun);
- }
- void cal(ll key,ll &coun)
- {
- top=;
- ll KK=;
- for(ll i=prime[]; i<=key; i=prime[++KK])
- {
- if(key%i==)
- {
- cnt[top++]=i;
- key/=i;
- while(key%i==)
- key/=i;
- }
- }
- if(key!=)
- {
- cnt[top++]=key;
- }
- for(ll i=; i<top; i++)
- {
- dfs(i,,cnt[i],coun);
- }
- }
- int main()
- {
- int T,K=;
- init();
- scanf("%d",&T);
- while(T--)
- {
- scanf("%I64d%I64d%I64d%I64d%I64d",&a,&b,&c,&d,&x);
- if(x == || x > b || x > d)
- {
- printf("Case %d: 0\n",++K);
- continue;
- }
- b/=x;
- d/=x;
- sum=;
- if(b>d) swap(b,d);
- //cout<<"b=="<<b<<" "<<"d=="<<d<<endl;
- for(int i=; i<=b; i++)
- {
- sum+=phi[i];
- }
- //cout<<"sumsss=="<<sum<<endl;
- for(ll i=b+; i<=d; i++)
- {
- if(su[i])
- {
- sum+=b;
- continue;
- }
- ll coun=;
- cal(i,coun);
- sum+=(b-coun);
- }
- printf("Case %d: %I64d\n",++K,sum);
- }
- return ;
- }
HDU1695:GCD(容斥原理+欧拉函数+质因数分解)好题的更多相关文章
- T^TOJ - 1251 - 。◕‿◕。TMD - 欧拉函数 - 质因数分解
http://www.fjutacm.com/Problem.jsp?pid=1251 想了很久,一开始居然还直接枚举因子d,计算重复了. 首先你要找与n的最大公因子大于m的x的个数. \[\sum\ ...
- HDU1695 GCD (欧拉函数+容斥原理)
F - GCD Time Limit:3000MS Memory Limit:32768KB 64bit IO Format:%I64d & %I64u Submit Stat ...
- HDU 1695 GCD (容斥原理+欧拉函数)
题目链接 题意 : 从[a,b]中找一个x,[c,d]中找一个y,要求GCD(x,y)= k.求满足这样条件的(x,y)的对数.(3,5)和(5,3)视为一组样例 . 思路 :要求满足GCD(x,y) ...
- HDU 1695 GCD(欧拉函数+容斥原理)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1695 题意:x位于区间[a, b],y位于区间[c, d],求满足GCD(x, y) = k的(x, ...
- hdu 1695 GCD (欧拉函数、容斥原理)
GCD Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submis ...
- HDU 1695 GCD (欧拉函数+容斥原理)
GCD Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submiss ...
- hdu 1695 GCD(欧拉函数+容斥)
Problem Description Given 5 integers: a, b, c, d, k, you're to find x in a...b, y in c...d that GCD( ...
- HDU2588:GCD(欧拉函数的应用)
题目链接:传送门 题目需求:Given integers N and M, how many integer X satisfies 1<=X<=N and (X,N)>=M.(2& ...
- hdu2588 GCD (欧拉函数)
GCD 题意:输入N,M(2<=N<=1000000000, 1<=M<=N), 设1<=X<=N,求使gcd(X,N)>=M的X的个数. (文末有题) 知 ...
随机推荐
- delegate、Func、Action几个常用手法
委托是我们C#开发当中使用频率非常的高一个手段,好处我就不列举了. 委托早期版本中只有delegate,后期版本有了Func(有返回值)和Action(无返回值)两委托方法. 我这里将列举它们三个常用 ...
- Java中的各种加密算法
Java中为我们提供了丰富的加密技术,可以基本的分为单向加密和非对称加密 1.单向加密算法 单向加密算法主要用来验证数据传输的过程中,是否被篡改过. BASE64 严格地说,属于编码格式,而非加密算法 ...
- Java类的设计----Object 类
Object类 Object类是所有Java类的根父类如果在类的声明中未使用extends关键字指明其父类,则默认父类为Object类 public class Person { ... } 等价于: ...
- nagios监控mysql
在nagios上部署check_mysql_health 监控mysql 博客分类: 架构 本监控为基于nagios服务器主动监控方法,利用check_mysql_health实现多种监控模式: ...
- capitalize()
capitalize() 是字符串的一个方法,用于把字符串的第一个字母转换成大写 In [1]: str = 'hello world' In [2]: str.capitalize() Out[2] ...
- 批量执行命令:fabric
Fabric 可以通过 SSH 在多台客户端主机上批量执行任务,是基于 paramiko 封装开发的,paramiko 更底层一些,安装方法如下: [root@localhost ~]$ yum in ...
- 解决Xcode "The selected destination does not support the architecture " 错误错误
XCODE编译运行项目后,发现工程编译后无法运行,出现:"The selected destination does not support the architecture for whi ...
- RegisterHotKey注册快捷键
RegisterHotKey的具体使用方使用方法如下: BOOL RegisterHotKey( HWND hWnd, //响应该热键的窗口句柄 Int id, ...
- CSS3 Transform变形(2D转换)
Transform:对元素进行变形:Transition:对元素某个属性或多个属性的变化,进行控制(时间等),类似flash的补间动画.但只有两个关键贞.开始,结束.Animation:对元素某个属性 ...
- poj_3436 网络最大流
题目大意 生产电脑的工厂将一台电脑分成P个部件来进行流水线生产组装,有N个生产车间,每个车间可以将一个半成品电脑添加某些部件,使之成为另一个半成品电脑或者成为一台完好的电脑,且每个车间有一个效率,即在 ...