問題描述:
對於任何正整數x,起約數的個數記做g(x).例如g(1)=1,g(6)=4.
如果某個正整數x滿足:對於任意i(0
現在給乙個n,求出不超過n的最大的反素數.
比如:輸入1000 輸出 840
思維過程:
求[1..n]中約數在大的反素數-->求約數最多的數
如果求約數的個數 756=2^2*3^3*7^1
(2+1)*(3+1)*(1+1)=24
基於上述結論,給出演算法:按照質因數大小遞增順序搜尋每乙個質因子,列舉每乙個質因子
為了剪枝:
性質一:乙個反素數的質因子必然是從2開始連續的質數.
因為最多隻需要10個素數構造:2,3,5,7,11,13,17,19,23,29
性質二:p=2^t1*3^t2*5^t3*7^t4.....必然t1>=t2>=t3>=....
反素數求解函式:
#include
#include
#define ll long long
using namespace std;
const int inf = 999999999;
const int prime[16]= ;
int n;
ll bnum,bsum;
//當前列舉到的數;列舉到的第k大的質因子;該數的約數個數;質因子個數上限。
void getantiprime(ll num,ll k,ll sum,ll limit)
//如果約數個數更多,將最優解更新為當前數。
if (bsum < sum)
bsum = sum;
bnum = num;
//如果約數個數相同,將最優解更新為較小的數。
if (bsum == sum && bnum > num) bnum = num;
if (k > 10) return ;
ll tmp = num;
//開始列舉每個質因子的個數。
for (int i = 1; i <= limit; ++i)
if (tmp*prime[k] > n) break;
tmp = tmp*prime[k];
getantiprime(tmp,k + 1,sum*(i + 1),i);
int main()
int t;
scanf("%d",&t);
while (t--)
bsum = -inf; bnum = inf;
scanf("%d",&n);
getantiprime(1,1,1,50);
printf("%lld\n",bnum);
return 0;
反素數打表函式:
#include
#include
#include
#define maxn 600000
using namespace std;
int dp[600001];
int main()
int i,j;
freopen("out.txt","w",stdout);
memset(dp,0,sizeof(dp));
for(i=1;i<=maxn;i++)
for(j=1;i*j<=maxn;j++)
dp[i*j]++;
int max=0;
for(i=2;i<=maxn;i++)
if(dp[i]>max)
max=dp[i];
cout<
cout<
max=0;
for(i=2;i<=maxn;i++)
if(dp[i]>max)
max=dp[i];
cout<
return 0;
int antip = ;
int pnum = ;
反素數求解 反素數打表
問題描述 對於任何正整數x,起約數的個數記做g x 例如g 1 1,g 6 4.如果某個正整數x滿足 對於任意i 0現在給乙個n,求出不超過n的最大的反素數.比如 輸入1000 輸出 840 思維過程 求 1.n 中約數在大的反素數 求約數最多的數 如果求約數的個數 756 2 2 3 3 7 1 ...
反素數求解 反素數打表
問題描述 對於任何正整數x,起約數的個數記做g x 例如g 1 1,g 6 4.如果某個正整數x滿足 對於任意i 0現在給乙個n,求出不超過n的最大的反素數.比如 輸入1000 輸出 840 思維過程 求 1.n 中約數在大的反素數 求約數最多的數 如果求約數的個數 756 2 2 3 3 7 1 ...
反素數總結
先來一發 大牛的總結 1.求乙個最小的數x使得他的因子數為n 每個數的因子數為 每個質因數的指數 1後相乘。建立搜尋樹後去找最小的滿足條件的數x,注意剪枝。然後因為要找最小的,所以隨著質因數的變大,指數是非遞增的。如果指數反而變大,交換前後的指數,因子數不變,但數變小了。include includ...