HDU 2841 Visible Trees 数论+容斥原理
来源:互联网 发布:看high类似软件 编辑:程序博客网 时间:2024/05/16 11:44
Description
If two trees and Sherlock are in one line, Farmer Sherlock can only see the tree nearest to him.
Input
Output
Sample Input
Sample Output
容斥原理
题意:给n*m的矩阵有点,左下角的点为(1,1),右上角的点(n,m),(其实转回来也是没影响的即m*n),一个人站在(0,0)看这些点,在一条直线的视线上,它只能看到最前面的那个点,后面的点将会被档住他看不到,问你,这个人一共能看到多少个点。
这个问题只要画一下图不难发现,如果一个点(x,y),x和y有非1的公约数z,那么他们其实可以一起缩小为(x/z,y/z),试着把这两个点和(0,0)连线,发现他们其实是同一条直线,而(x/z,y/z)
在前面,所以其实(x,y)被挡住了看不到的,这启发了我们,如果我们找到了x和y的最大公约数g,那么(x/g,y/g)一定是这条直线上最前面的点,没有其他店能挡住他,他一定能被看到,而他后面的点都看不到,那么(x/g,y/g)满足的性质就是,这两个数字互质
从而得到一个结论,两个数字(x,y)如果两数互质,则可以被看到,如果不互质,则看不到,所以我们就是要找出所有的二元组(x,y)使他们互质
我们可以固定一个数字,用一个数来循环。例如矩阵为n*m,我们固定m,用n来循环,即1与[1,m]里面多少个数互质,2与[1,m]里面多少个数互质,3与[1,m]里面多少个数互质……n与[1,m]里面多少个数互质,把这些结果全部累加起来即可
所以问题的最后变为了,给定一个数字x,怎么找出它和1到y里面有多少个数互质呢?
两个数字互质,其实就是它们没有公共的质因子,反过来两个数字有公共的质因子则一定不互质,那么我们可以求反面,x与1到y里面多少个数字不互质,然后用y减去即可
在这里我们就用到了容斥原理:先找到有多少个数和x有1个公共的质因子,然后加上;再找到有多少个数与x有2个公共的质因子,然后减去;再找到有多少个数有多少个数与x有3个公共的质因子,然后加上……最后得到的个数,就是有多少个数与x不互质
因为容斥原理一个最基本的准则就是——
要计算几个集合并集的大小,我们要先将所有单个集合的大小计算出来,然后减去所有两个集合相交的部分,再加回所有三个集合相交的部分,再减去所有四个集合相交的部分,依此类推,一直计算到所有集合相交的部分。(奇数加,偶数减)
1.dfs搜索遍历
#include <iostream>#include <stdio.h>using namespace std;typedef long long ll;bool isp[1010];int prime[1010],cnt,pp[1010],cnt0,n,m;ll ans;void pr(){ cnt=0; for(int i=2;i<=1000;i++) { if(!isp[i]) { prime[cnt++]=i; for(int j=i+i;j<=1000;j=j+i) isp[j]=true; } }}void cal(int cur){ cnt0=0; for(int i=0;prime[i]*prime[i]<=cur;i++) { if(cur%prime[i]==0) { pp[cnt0++]=prime[i]; while(cur%prime[i]==0) cur/=prime[i]; } } if(cur!=1) pp[cnt0++]=cur;}void dfs(int hav,int cur,int num){ if(hav>m||cur>=cnt0) return ; for(int i=cur;i<cnt0;i++) { int temp=hav*pp[i]; if(num&1) ans-=m/temp; else ans+=m/temp; dfs(temp,i+1,num+1); }}int main(){ pr(); int t; scanf("%d",&t); while(t--) { scanf("%d%d",&n,&m); ans=m; for(int i=2;i<=n;i++) { cal(i); ans+=m; for(int j=0;j<cnt0;j++) { ans-=m/pp[j]; dfs(pp[j],j+1,2); } } cout<<ans<<endl; } return 0;}
2.二进制枚举
#include <iostream>#include <stdio.h>using namespace std;typedef long long ll;bool isp[1010];int prime[1010],cnt,pp[1010],cnt0,n,m;ll ans;void pr(){ cnt=0; for(int i=2;i<=1000;i++) { if(!isp[i]) { prime[cnt++]=i; for(int j=i+i;j<=1000;j=j+i) isp[j]=true; } }}void cal(int cur){ cnt0=0; for(int i=0;prime[i]*prime[i]<=cur;i++) { if(cur%prime[i]==0) { pp[cnt0++]=prime[i]; while(cur%prime[i]==0) cur/=prime[i]; } } if(cur!=1) pp[cnt0++]=cur;}int main(){ pr(); int t; scanf("%d",&t); while(t--) { scanf("%d%d",&n,&m); ans=m; for(int x=2;x<=n;x++) //不是1~n-1 { ans+=m; //每次都要加m cal(x); //这里要注意分解的是x for(int i=1;i<(1<<cnt0);i++) { ll tmp=1,flag=0; for(int j=0;j<cnt0;j++) { if(i&(1<<j)) { tmp*=pp[j]; flag++; if(tmp>m) break; } } if(flag&1) ans-=m/tmp; else ans+=m/tmp; } } cout<<ans<<endl; } return 0;}
- HDU 2841 Visible Trees (数论,容斥原理)
- HDU 2841Visible Trees(容斥原理,数论)
- HDU 2841 Visible Trees 数论+容斥原理
- Hdu 2841 Visible Trees 容斥原理
- hdu 2841 Visible Trees(容斥原理)
- HDU 2841 - Visible Trees (容斥原理)
- hdu 2841 Visible Trees【容斥原理】
- hdu 2841 Visible Trees (容斥原理)
- HDU 2841 Visible Trees(容斥原理)
- [HDU 2841]Visible Trees:容斥原理
- [思维+容斥原理] hdu 2841 Visible Trees
- HDU 2841-Visible Trees(容斥原理)
- 【HDU】2841 - Visible Trees(容斥原理)
- HDU 2841 Visible Trees (容斥原理好题)
- HDU 2841:Visible Trees (容斥原理)
- HDU 2841 Visible Trees (素因子分解,容斥原理)
- 【HDU 2841】Visible Trees(容斥原理-好题)
- hdu 2841 Visible Trees(容斥原理)
- HDU 5651 xiaoxin juju needs help 逆元
- HDU1695 GCD (欧拉函数+容斥原理)
- 程序员之路——一个老程序员对刚上大学的学弟学妹的忠告
- UVA11806-Cheerleaders(容斥原理+二进制)
- 解析Json 出现——java.lang.RuntimeException: java.lang.reflect.InvocationTargetException
- HDU 2841 Visible Trees 数论+容斥原理
- UVA 10325 The Lottery( 容斥原理)
- iOS之一个超赞的视频直播、第三方库,直播看这个就够了,支持RTMP推流,美颜直播
- HDU 4334 Trouble (暴力)
- POJ 3904 Sky Code (容斥原理)
- Kubernetes& swarm对比
- Shell命令
- HDU 4059 容斥原理+快速幂+逆元
- HDU5072 容斥原理