1. 程式人生 > >51nod 1040 1060 (數論)

51nod 1040 1060 (數論)

51nod 1040 傳送門:https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1040

求1-n與n的gcd之和,n<=1e9

一個一個求肯定是不行的,所以需要一些方法咯

首先,如果x與n的gcd為gcd(x,n),所以gcd(x/gcd(x,n),n/gcd(x,n))=1,所以我們可以搜尋n的因子nn,然後求nn的尤拉函式(與nngcd為1的數字個數為tmp),然後tmp*n/nn就是gcd為n/nn的數字的gcd之和。

先求出n的尤拉函式phi,然後對於一個素因子k,如果k只有一個,n/k的尤拉函式為phi/(k-1),否則n/k的尤拉函式為phi/k

通過搜尋n的每一個因子,答案為sigma(phi[d]*n/d)(d|n)

#include <map>
#include <set>
#include <stack>
#include <queue>
#include <cmath>
#include <string>
#include <vector>
#include <cstdio>
#include <cctype>
#include <cstring>
#include <sstream>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#pragma comment(linker,"/STACK:102400000,102400000")

using namespace std;
#define   MAX           1000005
#define   MAXN          1000005
#define   maxnode       15
#define   sigma_size    30
#define   lson          l,m,rt<<1
#define   rson          m+1,r,rt<<1|1
#define   lrt           rt<<1
#define   rrt           rt<<1|1
#define   middle        int m=(r+l)>>1
#define   LL            long long
#define   ull           unsigned long long
#define   mem(x,v)      memset(x,v,sizeof(x))
#define   lowbit(x)     (x&-x)
#define   pii           pair<int,int>
#define   bits(a)       __builtin_popcount(a)
#define   mk            make_pair
#define   limit         10000

//const int    prime = 999983;
const int    INF   = 0x3f3f3f3f;
const LL     INFF  = 0x3f3f;
const double pi    = acos(-1.0);
const double inf   = 1e18;
const double eps   = 1e-8;
const LL    mod    = 1e9+7;
const ull    mx    = 133333331;

/*****************************************************/
inline void RI(int &x) {
      char c;
      while((c=getchar())<'0' || c>'9');
      x=c-'0';
      while((c=getchar())>='0' && c<='9') x=(x<<3)+(x<<1)+c-'0';
 }
/*****************************************************/

bool prime[100005];
int pr[100005];
int tot;
vector<int> v;
set<int> s;
LL ans;
int n;
void init(){
    mem(prime,0);tot=0;
    for(int i=2;i<100000;i++){
        if(!prime[i]){
            for(int j=2*i;j<100000;j+=i) prime[j]=1;
            pr[tot++]=i;
        }
    }
}

void dfs(int x,int ph,int j){
    if(s.count(x)) return ;
    else{
        s.insert(x);
        ans+=(LL)ph*(n/x);
    }
    for(int i=j;i<v.size();i++){
        int tmp=ph;
        int k=x;
        while(k%v[i]==0){
            k/=v[i];
            if(k%v[i]==0) tmp/=v[i];
            else tmp/=(v[i]-1);
            dfs(k,tmp,j+1);
        }
    }
}

int main(){
    //freopen("in.txt","r",stdin);
    cin>>n;
    init();
    v.clear();
    int k=n;
    for(int i=0;i<tot&&pr[i]*pr[i]<=k;i++){
        if(k%pr[i]==0){
            while(k%pr[i]==0) k/=pr[i];
            v.push_back(pr[i]);
        }
    }
    if(k!=1) v.push_back(k);
    int phi=n;
    for(int i=0;i<v.size();i++){
        phi=phi/v[i]*(v[i]-1);
    }
    ans=0;
    dfs(n,phi,0);
    cout<<ans<<endl;
    return 0;
}

51nod 1060 傳送門:https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1060

求1-n裡面因子數量最多的,並且最小的數

n<=1e18

由於1e18分解質因數,也就最多60多個數相乘,所以可以直接爆搜解決問題

因為a=p1^k1 * p2^k2 * p3^k3 *...* pn^kn

它的因子數量為(k1+1)*(k2+1)*(k3+1)*...*(kn+1)

所以搜尋時記錄當前值的大小,和這會應該搜尋的素因子pi,以及當前因子個數,每次搜尋往下都是搜尋後一種素因子,不在同一個素因子上遞迴

#include <map>
#include <set>
#include <stack>
#include <queue>
#include <cmath>
#include <string>
#include <vector>
#include <cstdio>
#include <cctype>
#include <cstring>
#include <sstream>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#pragma comment(linker,"/STACK:102400000,102400000")

using namespace std;
#define   MAX           1000005
#define   MAXN          1000005
#define   maxnode       15
#define   sigma_size    30
#define   lson          l,m,rt<<1
#define   rson          m+1,r,rt<<1|1
#define   lrt           rt<<1
#define   rrt           rt<<1|1
#define   middle        int m=(r+l)>>1
#define   LL            long long
#define   ull           unsigned long long
#define   mem(x,v)      memset(x,v,sizeof(x))
#define   lowbit(x)     (x&-x)
#define   pii           pair<int,int>
#define   bits(a)       __builtin_popcount(a)
#define   mk            make_pair
#define   limit         10000

//const int    prime = 999983;
const int    INF   = 0x3f3f3f3f;
const LL     INFF  = 0x3f3f;
const double pi    = acos(-1.0);
const double inf   = 1e18;
const double eps   = 1e-8;
const LL    mod    = 1e9+7;
const ull    mx    = 133333331;

/*****************************************************/
inline void RI(int &x) {
      char c;
      while((c=getchar())<'0' || c>'9');
      x=c-'0';
      while((c=getchar())>='0' && c<='9') x=(x<<3)+(x<<1)+c-'0';
 }
/*****************************************************/

LL n;
LL ans;
int maxn;
bool prime[10005];
int pr[10005];
int tot;
void init(){
    mem(prime,0);tot=0;
    for(int i=2;i<10000;i++){
        if(!prime[i]){
            for(int j=i*i;j<10000;j+=i) prime[j]=1;
            pr[tot++]=i;
        }
    }
}

void dfs(int f,int num,int nu,LL tmp){
    LL ret=tmp;
    if(tmp<=n){
        if(nu>maxn){
            maxn=nu;
            ans=tmp;
        }
        else if(nu==maxn) ans=min(ans,tmp);
    }
    for(int i=1;i<=num;i++){
        if(ret>n/pr[f]) break;//防止爆LL
        ret*=pr[f];
        dfs(f+1,i,nu*(i+1),ret);
    }
}
int main(){
    //freopen("in.txt","r",stdin);
    int t;
    cin>>t;
    init();
    while(t--){
        cin>>n;
        maxn=0;
        ans=0;
        dfs(0,100,1,1);
        cout<<ans<<" "<<maxn<<endl;
    }
    return 0;
}


相關推薦

51nod 1040 1060 數論

51nod 1040 傳送門:https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1040 求1-n與n的gcd之和,n<=1e9 一個一個求肯定是不行的,所以需要一些方法咯 首先,如果x與n的

數論51NOD 1106 質數檢測

ret == max else 篩法 %s out spa clas 給出N個正整數,檢測每個數是否為質數。如果是,輸出"Yes",否則輸出"No"。 Input 第1行:一個數N,表示正整數的數量。(1 <= N <= 1000) 第2 - N +

數論51NOD 1135 原根

for text 分解 fin 輸出 def gray div F12 設m是正整數,a是整數,若a模m的階等於φ(m),則稱a為模m的一個原根。(其中φ(m)表示m的歐拉函數) 給出1個質數P,找出P最小的原根。 Input 輸入1個質數P(3 <= P

51Nod 1217 - Minimum Modular數論

【題目描述】 【思路】 這個題我們可以考慮從小到大列舉m(從max(1,n-k)到max(a[i])+1),然後判斷能否在刪不超過k個數的情況下滿足每個數模m都互不相同。 對於模m的情況,a[i]≡a[j](mod m)當且僅當a[i]-a[j]是m的倍數,我們可以先預處理出a[i

51nod-1616 最小集合數論

基準時間限制:1 秒 空間限制:131072 KB 分值: 80 難度:5級演算法題  收藏  關注 A君有一個集合。 這個集合有個神奇的性質。 若X,Y屬於該集合,那麼X與Y的最大公因數也屬於該集合。 但是他忘了這個集合中原先有哪些數字。 不過幸運的是,他

UVA 10042 Smith Numbers數論

sizeof ret col 保存 進行 uva nal isp published Smith Numbers Background While skimming his phone directory in 1982, Albert Wilansky, a ma

[luoguP1069] 細胞分裂數論

def getc urn ostream lin 優先級 org return 優先 傳送門 分解質因數,不說了 這題坑了我2個多小時 教訓 不熟悉位運算的優先級一定要加括號!!!! #include <cstdio> #include &

UVA571 - Jugs數論

osi com con post roc defined ucc sof mic UVA571 - Jugs(數論) 題目鏈接 題目大意:給你A和B的水杯。給你三種操作:fill X:把X杯裏面加滿水。empty X:把X杯中的水清空。pou

LibreOJ #6220. sum數論

define onclick const 全部 註意 img long long %d mes   題目大意:在數組中找出一些數,使它們的和能被n整除   這題標簽是數學,那我就標題就寫數論好了...   顯然如果數組中有n的倍數直接取就行。   那假設數組中沒有n的

bzoj1257: [CQOI2007]余數之和sum數論

img const ima left class -1 找到 一段 max   非常經典的題目...   要求      則有   實際上   最多只有2*sqrt(k)種取值,非常好證明   因為>=sqrt(k)的數除k下取整得到的數一定<=sq

【LightOJ1336】Sigma Function數論

【LightOJ1336】Sigma Function(數論) 題面 Vjudge 求和運算是一種有趣的操作,它來源於古希臘字母σ,現在我們來求一個數字的所有因子之和。例如σ(24)=1+2+3+4+6+8+12+24=60.對於小的數字求和是非常的簡單,但是對於大數字求和就比較困難了。現在給你一個n,你需要

UVa 11582 - Colossal Fibonacci Numbers!數論

targe ros family tdi 計算 com fibonacci numbers def 鏈接: https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=

CF 980D Perfect Groups數論

數論 for AS AI 子串 次數 我們 main 發現 CF 980D Perfect Groups(數論) 一個數組a的子序列劃分僅當這樣是合法的:每個劃分中的任意兩個數乘積是完全平方數。定義a的權值為a的最小子序列劃分個數。現在給出一個數組b,問權值為i的b的子串

【BZOJ3240】【NOI2013】矩陣遊戲數論

char ++i getc getchar() 系列 HP 推導 max long long 【BZOJ3240】【NOI2013】矩陣遊戲(數論) 題面 BZOJ 題解 搞什麽矩陣十進制快速冪加卡常? 直接數學推導不好嗎? 首先觀察如何從每一行的第一個推到最後一個 \(f

【HDOJ5640】King's Cake數論

nbsp std namespace cas algo ima iostream turn tdi 題意: 思路: 1 #include<cstdio> 2 #include<cstdlib> 3 #include<iostream

數論逆元的線性算法

div 逆元 線性 ++ === class 就是 color pre 證明:/ P=K*I+R      (R<I,  1<I<P); K*I+R=0(MOD P)===(兩邊同時,乘以i-1,r-1)===>i-1=-k*r-1 r-1=(p m

[Project Euler 429] Sum of squares of unitary divisors數論

blog ont namespace href 題解 str return void rap 題目鏈接:https://projecteuler.net/problem=429 題目: A unitary divisor dd of a number nn is a d

BZOJ2299 HAOI2011向量數論

條件 n) char string getchar() font while [] ||   設最後的組成為x=x0a+x1b,y=y0a+y1b。那麽容易發現x0和y0奇偶性相同、x1和y1奇偶性相同。於是考慮奇偶兩種情況,問題就變為是否存在x和y使ax+by=c,那麽其

BZOJ2721 Violet5櫻花數論

+= || algo ont flag int math ons violet   有(x+y)n!=xy。套路地提出x和y的gcd,設為d,令ad=x,bd=y。則有(a+b)n!=abd。此時d已是和a、b無關的量。由a與b互質,得a+b與ab互質,於是將a+b除過來得

BZOJ3240 NOI2013矩陣遊戲數論

ring cout ios ble har using namespace tmp urn   必修五題。 // luogu-judger-enable-o2 #include<iostream> #include<cstdio> #includ