Description
Ponder This Challenge:
What is the minimal number, X, of yes/no questions needed to find the smallest (but more than 1*) divisor of a number between 2 and 166 (inclusive)?
We are asking for the exact answer in two cases:
In the worst case, i.e., what is the smallest number X for which we can guarantee finding it in no more than X questions?
On average, i.e., assuming that the number was chosen in uniform distribution from 2 to 166 and we want to minimize the expected number of questions.
* For example, the smallest divisor of 105 is 3, and of 103 is 103.
Update (11/05): You should find the exact divisor without knowing the number and answering “prime” is not a valid.
题解
第一问
要最少的步数达到答案,肯定是采用二分的策略,直接按照二分的步骤模拟就可以。
第二问
像第一问那样二分的过程肯定不能得到期望最小步数。考虑答案,其实就是
代码
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#define maxn 100006
#define nn 1e9
using namespace std;
inline char nc(){
static char buf[100000],*i=buf,*j=buf;
return i==j&&(j=(i=buf)+fread(buf,1,100000,stdin),i==j)?EOF:*i++;
}
inline int _read(){
int sum=0;char ch=nc();
while(!(ch>='0'&&ch<='9'))ch=nc();
while(ch>='0'&&ch<='9')sum=sum*10+ch-48,ch=nc();
return sum;
}
struct data{
int x,p;
bool operator <(const data&b)const{return p<b.p;}
}a[maxn];
int n,m,tot,ans,w[maxn],prime[maxn];
bool vis[maxn];
priority_queue< int,vector<int>,greater<int> > heap;
void make_prime(){
memset(vis,1,sizeof(vis));
for(int i=2;i<=sqrt(sqrt(nn));i++) if(vis[i])
for(int j=2;j<=sqrt(nn)/i;j++) vis[i*j]=0;
for(int i=2;i<=sqrt(nn);i++) if(vis[i])prime[++prime[0]]=i;
}
int main(){
freopen("prime.in","r",stdin);
freopen("prime.out","w",stdout);
n=_read();
make_prime();
for(int i=1;i<=n;i++){
a[i].x=_read();
for(int j=1;j<=prime[0];j++) if(!(a[i].x%prime[j])){
a[i].p=prime[j];break;
}
if(!a[i].p)a[i].p=a[i].x;
}
sort(a+1,a+1+n);
for(int i=1;i<=n;i++){
if(a[i].p!=a[i-1].p)m++;
w[m]++;
}
int x=m;
while(x>1){ans++;x=(x+1)/2;}
printf("%d\n",ans);ans=0;
for(int i=1;i<=m;i++)heap.push(w[i]);
for(int i=1;i<m;i++){
int x=heap.top();heap.pop();
int y=heap.top();heap.pop();
ans+=x+y;heap.push(x+y);
}
printf("%.6lf",(double)ans/n);
return 0;
}