1. 程式人生 > >[POI2002][HAOI2007]反素數(Antiprime)

[POI2002][HAOI2007]反素數(Antiprime)

鏈接 sin ant int strong 十個 mes poi org

題目鏈接

這道題需要用到整數唯一分解定理以及約數個數的計算公式。這裏我就不再闡述了。

公式可以看出,只有指數影響約數個數,那麽在唯一分解出的乘式中,指數放置的任何位置都是等價的。(即 23*34*57與27*34*53的約數個數相同)但很明顯指數放置位置的不同會影響乘積的大小。由於所有比n小的數的約數個數都比他的約數個數小,換而言之就是約數個數不相等。即 相同約數個數,該數越小越好。那麽我們運用貪心思想。盡量大的指數放置於盡量小的底數上。

題目的數據範圍小於231,所以指數最大31,由之前的推論,若底數遞增,則有指數遞減。直接dfs。減一下枝,質因數最多只有十個,這題就十分簡單了。

#include<cmath>
#include
<iostream> #include<cstdio> #include<algorithm> #define ll long long using namespace std; ll read(){ ll res=0,f=1; char ch=getchar(); while(ch<0||ch>9){ if(ch==-)f=-1; ch=getchar(); } while(ch>=0&&ch<=9){ res
=res*10+(ch-0); ch=getchar(); } return res*f; } int p[20]={0,2,3,5,7,11,13,17,19,23,29}; ll n,s,s1; void f(ll x,ll y,ll m,ll z){ if(x>=11)return; ll k=1; for(int i=1;i<=m;++i){ k*=p[x]; if(y*k>n)return; if(z*(i+1)==s1&&y*k<s)s=y*k;
if(z*(i+1)>s1)s=y*k,s1=z*(i+1); f(x+1,y*k,i,z*(i+1)); } } int main(){ n=read(); f(1,1,31,1); cout<<s; return 0; }

[POI2002][HAOI2007]反素數(Antiprime)