GCD&&LCM的一些经典问题
1.1~n的全部数的最小公倍数:lightoj 1289 传送门
分析:素因子分解可知这个数等于小于1~n的全部素数的最高次幂的乘积
预处理1~n的全部质数,空间较大,筛选的时候用位图来压缩。和1~n全部
质数的乘积,剩下的就是找最高次幂的问题了。
代码例如以下:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <set>
#include <map>
#include <queue>
#define PB push_back
#define MP make_pair
#define REP(i,n) for(int i=0;i<(n);++i)
#define FOR(i,l,h) for(int i=(l);i<=(h);++i)
#define DWN(i,h,l) for(int i=(h);i>=(l);--i)
#define IFOR(i,h,l,v) for(int i=(h);i<=(l);i+=(v))
#define CLR(vis) memset(vis,0,sizeof(vis))
#define MST(vis,pos) memset(vis,pos,sizeof(vis))
#define MAX3(a,b,c) max(a,max(b,c))
#define MAX4(a,b,c,d) max(max(a,b),max(c,d))
#define MIN3(a,b,c) min(a,min(b,c))
#define MIN4(a,b,c,d) min(min(a,b),min(c,d))
#define PI acos(-1.0)
#define INF 1000000000
#define LINF 1000000000000000000LL
#define eps 1e-8
#define LL long long
using namespace std; const int maxn = 1e8+10; typedef unsigned int UI; UI tmp[5800000];
int vis[maxn/32+10];
int p[5800000],cnt; void init(){
cnt=0;
p[0]=tmp[0]=2;
cnt++;
IFOR(i,3,maxn-1,2){
if(!(vis[i/32]&(1<<(i%32)))){//用位图压缩节省空间
p[cnt]=i;
tmp[cnt]=tmp[cnt-1]*i;
cnt++;
IFOR(j,3*i,maxn-1,2*i) vis[j/32]|=(1<<(j%32));
}
}
} UI solve(int n){
int pos = upper_bound(p,p+cnt,n)-p-1;
UI ans = tmp[pos];
for(int i=0;i<cnt&&p[i]*p[i]<=n;i++){
int mul = p[i];
int ff=p[i]*p[i];
while(ff/mul==p[i]&&ff<=n){
mul=mul*p[i];
ff=ff*p[i];
}
ans=ans*(mul/p[i]);
}
return ans;
} int main()
{
init();
int t,cas=1,n;
scanf("%d",&t);
while(t--){
scanf("%d",&n);
printf("Case %d: %u\n",cas++,solve(n));
}
return 0;
}
2,1~n中最小公倍数等于n的数的对数 lightoj 1236传送门
非常明显这些数都是 n 的约数,
然后n=p1^a1*p1^a2*p3^a3...*pn^an;
对这两个数素因子分解要使得的每个素数ai的最高次等于ai,
因此对于每个因子的可能方案就有 (ai+1)*2-1;
代码例如以下:
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std; const int maxn = 1e7+10; int p[maxn/5],tot;
bool vis[maxn];
void init(){
tot=0;
memset(vis,0,sizeof(vis));
for(int i=2;i<maxn;i++){
if(!vis[i]){
p[tot++]=i;
for(int j=i+i;j<maxn;j+=i)
vis[j]=1;
}
}
} int main()
{
init();
int t,cas=1;
scanf("%d",&t);
while(t--){
long long n;
scanf("%lld",&n);
long long ans = 1;
for(int i=0;i<tot&&p[i]*p[i]<=n;i++){
if(n%p[i]==0){
long long cnt = 0;
while(n%p[i]==0)cnt++,n/=p[i];
ans=ans*(cnt*2+1);
}
}
if(n>1) ans*=3;
ans=ans/2+1;
printf("Case %d: %lld\n",cas++,ans);
}
return 0;
}
3. 1~n中随意两对数的最大公约数之和 UVA 11426 id=18553" target="_blank">传送门
我们设 f[n] = sigma(gcd(i , n)) 1<=i<n
那么 ans[n] = ans[n-1] + f[n];
在求f[n]的时候我们能够枚举gcd 然后f[n]+=gcd*phi(n/gcd);
代码例如以下:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm> #define PB push_back
#define MP make_pair
#define REP(i,n) for(int i=0;i<(n);++i)
#define FOR(i,l,h) for(int i=(l);i<=(h);++i)
#define DWN(i,h,l) for(int i=(h);i>=(l);--i)
#define IFOR(i,h,l,v) for(int i=(h);i<=(l);i+=(v))
#define CLR(vis) memset(vis,0,sizeof(vis))
#define MST(vis,pos) memset(vis,pos,sizeof(vis))
#define MAX3(a,b,c) max(a,max(b,c))
#define MAX4(a,b,c,d) max(max(a,b),max(c,d))
#define MIN3(a,b,c) min(a,min(b,c))
#define MIN4(a,b,c,d) min(min(a,b),min(c,d))
#define PI acos(-1.0)
#define INF 1000000000
#define LINF 1000000000000000000LL
#define eps 1e-8
#define maxn 4000001
#define LL long long
using namespace std; int phi[maxn]; LL ans[maxn];
LL f[maxn];
void init(){
FOR(i,1,maxn-1) phi[i]=i;
IFOR(i,2,maxn-1,2) phi[i]=phi[i]>>1;
IFOR(i,3,maxn-1,2){
if(phi[i]==i){
IFOR(j,i,maxn-1,i)
phi[j]=phi[j] -phi[j]/i;
}
}
} void solve(){
CLR(ans);
init();
FOR(i,1,maxn-1){
IFOR(j,i+i,maxn,i)
f[j]=f[j]+(LL)i*phi[j/i];
}
ans[1]=f[1];
FOR(i,2,maxn-1) ans[i]=ans[i-1]+f[i];
} int main()
{
solve();
int n;
while(~scanf("%d",&n)&&n){
printf("%lld\n",ans[n]);
}
return 0;
}
4.sigma(i,n) (1<=i<=n) 传送门
分析:
两个数的最小公倍数 = x*n/gcd(x,n);我们如果与n的最大公约数为g;
则与n的最大公约数的和g的最小公倍数的和为 n/g * (x1 + x2 + x3 + x(phi[n/g]))
小于等于n与n的最大公约数为g的数的个数为 Phi[n/h] 这里的phi表示的是欧拉函数
另一个结论就是 小于等于x与x互质的数的和 = phi[x]*x/2;
证明:
if gcd(n,i)=1 then gcd(n,n-i)=1 (1<=i<=n)
反证法:
假设存在K!=1使gcd(n,n-i)=k,那么(n-i)%k==0
而n%k=0
那么必须保证i%k=0
k是n的因子,假设i%k=0那么 gcd(n,i)=k,矛盾出现;
于是问题变的很easy: ANS=N*phi(N)/2
i,n-i总是成对出现,而且和是n
于是可能就有人问了,假设存在n-i=i那不是反复计算?
答案是不会
由于:
n=2*i->i=n/2
1.假设n是奇数,那么n!=2*i,自然也不存在 n-i=i和反复计算之说
2.假设n是偶数,n=2*i成立,gcd(n,n/2)必定为n的一个因子,这个因子为1当且仅当n==2
于是对于n>2的偶数。绝对不存在gcd(n,n/2)=1所以更别说什么反复计算了
对于n==2
ans=2*1/2=1,正好也满足
所以得到终于公式:
ans=N*phi(N)/2
因此这道题目的终于公式就是 n*sigma(phi[n/x]*n/x/2) x|n;
代码例如以下:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm> #define PB push_back
#define MP make_pair
#define REP(i,n) for(int i=0;i<(n);++i)
#define FOR(i,l,h) for(int i=(l);i<=(h);++i)
#define DWN(i,h,l) for(int i=(h);i>=(l);--i)
#define IFOR(i,h,l,v) for(int i=(h);i<=(l);i+=(v))
#define CLR(vis) memset(vis,0,sizeof(vis))
#define MST(vis,pos) memset(vis,pos,sizeof(vis))
#define MAX3(a,b,c) max(a,max(b,c))
#define MAX4(a,b,c,d) max(max(a,b),max(c,d))
#define MIN3(a,b,c) min(a,min(b,c))
#define MIN4(a,b,c,d) min(min(a,b),min(c,d))
#define PI acos(-1.0)
#define INF 1000000000
#define LINF 1000000000000000000LL
#define eps 1e-8
#define maxn 1000001
#define LL long long
using namespace std; //const LL mod = 1e9+7; int phi[maxn];
void init(){
FOR(i,1,maxn-1) phi[i]=i;
IFOR(i,2,maxn-1,2) phi[i]=phi[i]>>1;
IFOR(i,3,maxn-1,2){
if(phi[i]==i){
IFOR(j,i,maxn-1,i)
phi[j]=phi[j] -phi[j]/i;
}
}
} LL ans[maxn];
void solve()
{
init();
int i,j;
FOR(i,1,maxn-1){
IFOR(j,i,maxn-1,i)
ans[j]=ans[j]+(LL)phi[j/i]*(LL)j/i/2;
}
} int main()
{
solve();
int n,t;
scanf("%d",&t);
while(t--){
scanf("%d",&n);
printf("%lld\n",(ans[n]+1)*n);
}
return 0;
}
GCD&&LCM的一些经典问题的更多相关文章
- 最大公约数(GCD)与最小公倍数(LCM)的计算
给出两个数a.b,求最大公约数(GCD)与最小公倍数(LCM) 一.最大公约数(GCD) 最大公约数的递归: * 1.若a可以整除b,则最大公约数是b * 2.如果1不成立,最大公约数便是b ...
- ACM数论之旅3---最大公约数gcd和最小公倍数lcm(苦海无边,回头是岸( ̄∀ ̄))
gcd(a, b),就是求a和b的最大公约数 lcm(a, b),就是求a和b的最小公倍数 然后有个公式 a*b = gcd * lcm ( gcd就是gcd(a, b), ( •̀∀•́ ) ...
- Solve Equation gcd(x,y)=gcd(x+y,lcm(x,y)) gcd(x,y)=1 => gcd(x*y,x+y)=1
/** 题目:Solve Equation 链接:http://acm.hnust.edu.cn/JudgeOnline/problem.php?id=1643 //最终来源neu oj 2014新生 ...
- hdu 5974 A Simple Math Problem gcd(x,y)=gcd((x+y),lcm(x,y))
题目链接 题意 现有\[x+y=a\\lcm(x,y)=b\]找出满足条件的正整数\(x,y\). \(a\leq 2e5,b\leq 1e9,数据组数12W\). 思路 结论 \(gcd(x,y)= ...
- 最大公约数gcd与最小公倍数lcm
最大公约数:gcd 最大公倍数:lcm gcd和lcm的性质:(我觉得主要是第三点性质) 若gcd (
- 最大公约数gcd、最小公倍数lcm
最大公约数(辗转相除法) 循环: int gcd(int a,int b) { int r; ) { r=b%a; b=a; a=r; } return b; } 递归: int gcd(int a, ...
- Mathematics:GCD & LCM Inverse(POJ 2429)
根据最大公约数和最小公倍数求原来的两个数 题目大意,不翻译了,就是上面链接的意思. 具体思路就是要根据数论来,设a和b的GCD(最大公约数)和LCM(最小公倍数),则a/GCD*b/GCD=LCM/G ...
- POJ 2429 GCD & LCM Inverse (Pollard rho整数分解+dfs枚举)
题意:给出a和b的gcd和lcm,让你求a和b.按升序输出a和b.若有多组满足条件的a和b,那么输出a+b最小的.思路:lcm=a*b/gcd lcm/gcd=a/gcd*b/gcd 可知a/gc ...
- [POJ 2429] GCD & LCM Inverse
GCD & LCM Inverse Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 10621 Accepted: ...
随机推荐
- php的get_object_vars函数
我在看ecshop源码的时候,发现了一个非常有趣的函数,在此记下:get_object_vars() 从字面我们可以猜到,这个函数是针对类的一个方法:语法:array get_object_vars ...
- Django day08 多表操作 (一) 多表模型创建
多表模型创建分析:1)作者表:一个作者有姓名和年龄2)作者信息表: 有作者就有信息,点击作者的名字可以查询他的电话和地址, 作者表对应作者信息表,所以他们之间是一对一对的关系3)出版社表: 出版社有对 ...
- 显示程序输出并复制到文件(tee 命令)
Linux tee命令用于读取标准输入的数据,并将其内容输出成文件. tee指令会从标准输入设备读取数据,将其内容输出到标准输出设备,同时保存成文件. 语法 tee [-ai][--help][--v ...
- 五分钟学习React(六):元素(Element)和组件(Component)
俗话说"万丈高楼平地起",从这一期开始,我们将使用基于Webpack+Babel的React学习React框架中的一些基础概念.在学习React的过程中经常会把Element.Cl ...
- (转)vuex2.0 基本使用(3) --- getter
有的组件中获取到 store 中的state, 需要对进行加工才能使用,computed 属性中就需要写操作函数,如果有多个组件中都需要进行这个操作,那么在各个组件中都写相同的函数,那就非常麻烦,这 ...
- 关于改变安卓Button样式,这里有一个好方法。
首先,在drawable下创建一个新的xml文件(例如我创建的为button.xml).然后在里面输入以下代码. <item> <shape> <gradient and ...
- Deutsch lernen (10)
Dieser Weg Dieser Weg wird kein leichter sein. Dieser Weg wird steinig und schwer. Nicht mit vielen ...
- 利用jsonp进行Ajax跨域请求
在进行Ajax请求的时候经常会遇到跨域的问题,这个时候一般就会用到jsonp. 关于json和jsonp,网上有很多原理解释,这里就不多赘述,需要的自行搜索. 下面是一个简单的ajax跨域请求示例: ...
- (转)C#开发微信门户及应用(3)--文本消息和图文消息的应答
http://www.cnblogs.com/wuhuacong/p/3622636.html 微信应用如火如荼,很多公司都希望搭上信息快车,这个是一个商机,也是一个技术的方向,因此,有空研究下.学习 ...
- POJ_1061_扩展欧几里德
青蛙的约会 Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 107027 Accepted: 21321 Descript ...