反素數 Antiprime

題目描述

原題來自:POI 2001

如果一個大於等於 1 的正整數 n,滿足所有小於 n 且大於等於 1 的所有正整數的約數個數都小於 n 的約數個數,則 n 是一個反素數。譬如:1, 2, 4, 6, 12, 24,它們都是反素數。

請你計算不大於 n 的最大反素數。

輸入

一行一個正整數 n。

輸出

只包含一個整數,即不大於 n 的最大反素數。

樣例輸入

1000

樣例輸出

840

提示

數據範圍與提示

對於 10% 的數據,1≤n≤10^3;
對於 40% 的數據,1≤n≤10^6;
對於 100% 的數據,1≤n≤2×10^9。

來源/分類

ybttg 數論 

題解:

這題對我這種數學蒟蒻來說真是太難了

首先,這題需要用到兩個定理:唯一分解定理以及因數個數定理

唯一分解定理:任何一個大於1的自然數 N,如果N不爲質數,那麼N可以唯一分解成有限個質數的乘積

N=p1^{a1}*p2^{a2}*p3^{a3}...這裏p1<p2<p3<...<pn,且均爲質數

因數個數定理:

因數個數定理可以套用上面的式子——N=p1^{a1}*p2^{a2}*p3^{a3}...

而N的因數個數就爲:(a1+1)*(a2+1)*...(an+1)

總結一下,就是指數+1連乘

從公式可以看出——只有指數影響因數個數!

在唯一分解定理中可以看出指數放置的位置對於因數個數來說並不影響

舉個肥腸簡單的栗子:2^{3}*3^{5}*5^{7}2^{7}*3^{5}*5^{3}的因數個數相同

因爲所有小於n的數其因數個數都少於n,所以相同約數個數,數越小越好。

接下來可以運用一下貪心,得到一個策略:將盡量大的指數搭配在儘量小的質因數上

而數據範圍小於2^{31},所以指數最大31,直接dfs即可!

但是這道題還有一個坑點:那就是所有變量最好都開long long(否則就像我一樣,運行錯誤40%!)

代碼:

#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int prime[]={0,2,3,5,7,11,13,17,19,23,29,31};
ll n;
ll ans_num=0,ans_ges=0;
void dfs(ll now,ll ges,ll num,ll up)
{
    if(ges>ans_ges)
    {
    	ans_num=num; 
		ans_ges=ges;
	}
    else if(ges==ans_ges && num<ans_num) ans_num=num;
    for(int i=1;i<=up;i++)
    {
        num*=prime[now];
        if(num>n) return;
        dfs(now+1,ges*(i+1),num,i);
    }
}
int main()
{
    scanf("%lld",&n);
    dfs(1,1,1,31);
    printf("%lld\n",ans_num);
    return 0;
}

 

發佈了59 篇原創文章 · 獲贊 12 · 訪問量 4951
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章