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: ...
随机推荐
- [Spring] Spring Boot 生态
- selenium3+python-多窗口、句柄(handle)
一.获取当前窗口句柄 1.元素有属性,浏览器的窗口其实也有属性的,只是你看不到,浏览器窗口的属性用句柄(handle)来识别. 2.人为操作的话,可以通过眼睛看,识别不同的窗口点击切换.但是脚本没长眼 ...
- android 可拖动控件 ontouchevent
首先附上文章的转载内容的链接: 学习android 可拖动事件首先需要对android的屏幕和touchevent参数建立一个详细的知识结构. 1.android坐标系统 一.首先明确一下 andro ...
- POJ 3253 STL优先队列
题目大意:FJ需要修补牧场的围栏,他需要 N 块长度为 Li 的木头(N planks of woods).开始时,FJ只有一块无限长的木板,因此他需要把无限长的木板锯成 N 块长度 为 Li 的木板 ...
- 全局设置border-box
全局设置 border-box 很好,更符合我们通常对一个「盒子」尺寸的认知.,其次它可以省去一次又一次的加加减减,它还有一个关键作用——让有边框的盒子正常使用百分比宽度.但是使用了 border-b ...
- 五分钟学习React(六):元素(Element)和组件(Component)
俗话说"万丈高楼平地起",从这一期开始,我们将使用基于Webpack+Babel的React学习React框架中的一些基础概念.在学习React的过程中经常会把Element.Cl ...
- Android 在线升级
1.获取当前安装版本 //获取当前版本 public int getVersion(Context context){ ; try { version = context.getPackageMana ...
- Matlab数组创建
只用C语言,不用Matlab这种魔咒还是要打破的.Matlab是科学计算的常用工具,既然以前没用过,现在开始学吧...... 1. 向量的创建 1)直接输入: 行向量:a=[1,2,3,4,5] ...
- C# for 遍历 IPagedList
IPagedList<Doc> ss = Doclist.ToPagedList(page, pageSize); ;i<ss.Count;i++) { var yy = ss[i] ...
- eas之事件
选择事件 选择事件是在选择块发生变化后发出.table.addKDTSelectListener(new KDTSelectListener(){ public void tableSelect ...