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傳送門
我們設 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,矛盾出現;
於是問題變的非常簡單: 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;
}
相關文章
- 揹包問題的一道經典問題
- 一些Linux試題(經典!!)(轉)Linux
- 八數碼 經典問題
- SQL language裡面的經典問題SQL
- 機器學習教材中的 7 大經典問題機器學習
- 5個經典的前端面試問題前端面試
- 面試大型外企的專案經理――我對一些經典問題總結的英文回答模板(轉)面試
- 資料結構::一些經典的大資料題資料結構大資料
- 經典的 Top K 問題,你真的懂了麼?
- 四個經典的SQL程式設計問題SQL程式設計
- 70個經典的 Shell 指令碼面試問題指令碼面試
- 5個經典的JavaScript面試基礎問題JavaScript面試
- JavaScript閉包與變數的經典問題JavaScript變數
- 七大快取經典問題快取
- 經典演算法-最大流問題演算法
- CSS 佈局經典問題初步整理CSS
- 一些經典DOS命令
- fragment一些經典用法Fragment
- google經典演算法面試題-雞蛋問題Go演算法面試題
- 經典面試問題:12小球問題演算法(原始碼)面試演算法原始碼
- 剖析一些經典的CSS佈局問題,為前端開發+面試保駕護航CSS前端面試
- 非線性規劃的經典例題--選址問題
- 經典面試題面試題
- AT 經典90題
- 就是要你懂TCP–最經典的TCP效能問題TCP
- 【C++】 55_經典問題分析 四C++
- oracle經典亂碼問題——靠靠靠靠Oracle
- 30 個 Openstack 經典面試問題和解答面試
- c 語言指標操作經典問題指標
- 全面解析快取應用經典問題快取
- CSS中越界問題經典解決方案CSS
- 16個經典面試問題及回答思路面試
- TCP通訊之經典問題解決TCP
- 服務端經典的C10k問題(譯)服務端
- 解決SQL Server常見的七個經典問題SQLServer
- 70個經典面試問題,有備無患~面試
- 使用 JavaScript 解決經典爬樓梯問題JavaScript
- Dreamweaver製作網頁經典問題大整理網頁