Time Limit: 2 second(s) | Memory Limit: 32 MB |
Rimi learned a new thing about integers, which is - any positive integer greater than 1 can be divided by its divisors. So, he is now playing with this property. He selects a number N. And he calls this D.
In each turn he randomly chooses a divisor of D (1 to D). Then he divides D by the number to obtain new D. He repeats this procedure until D becomes 1. What is the expected number of moves required forN to become 1.
Input
Input starts with an integer T (≤ 10000), denoting the number of test cases.
Each case begins with an integer N (1 ≤ N ≤ 105).
Output
For each case of input you have to print the case number and the expected value. Errors less than 10-6 will be ignored.
Sample Input | Output for Sample Input |
3 1 2 50 | Case 1: 0 Case 2: 2.00 Case 3: 3.0333333333 |
dp[i]表示i经过期望值为多少步变为1
每个数选择它的因子的概率是一样的
#include <cstdio>
#include <iostream>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <string.h>
#include <string>
#include <vector>
#include <queue>
#define MEM(a,x) memset(a,x,sizeof a)
#define eps 1e-8
#define MOD 10009
#define MAXN 10010
#define MAXM 100010
#define INF 99999999
#define ll __int64
#define bug cout<<"here"<<endl
#define fread freopen("ceshi.txt","r",stdin)
#define fwrite freopen("out.txt","w",stdout)
using namespace std;
int Read()
{
char c = getchar();
while (c < '0' || c > '9') c = getchar();
int x = 0;
while (c >= '0' && c <= '9') {
x = x * 10 + c - '0';
c = getchar();
}
return x;
}
void Print(int a)
{
if(a>9)
Print(a/10);
putchar(a%10+'0');
}
double dp[100010];
bool vis[100010];
double dfs(int n)
{
if(n==1) return 0.0;
if(vis[n]) return dp[n];
double ans=1.0;
int a[1000];
int cnt=0;
for(int i=1;i*i<=n;i++)
{
if(n%i==0)
{
a[cnt++]=i;
if(i*i!=n)
a[cnt++]=n/i;
}
}
double p=1.0/(cnt*1.0);
for(int i=0;i<cnt;i++)
{
if(a[i]==1) continue;
ans+=dfs(n/a[i])*p;
}
ans=ans/(1.0-p);
dp[n]=ans;
vis[n]=1;
return ans;
}
int main()
{
//fread;
int tc;
int cs=1;
scanf("%d",&tc);
while(tc--)
{
int n;
scanf("%d",&n);
MEM(vis,0);
double ans=dfs(n);
printf("Case %d: %.6lf\n",cs++,ans);
}
return 0;
}
再贴一个代码
如果有n个因子 dp[N]=(dp[a1]+dp[a2]+……+dp[ak])/k+1(假设有k个因子分别为a1 a2 ……ak)
其中ak=N (k-1)dp[N]=dp[a1]+dp[a2]+……dp[ak-1]+k
所以dp[N]=(dp[a1]+dp[a2]+……dp[ak-1]+k)/(k-1)
#include <cstdio>
#include <iostream>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <string.h>
#include <string>
#include <vector>
#include <queue>
#define MEM(a,x) memset(a,x,sizeof a)
#define eps 1e-8
#define MOD 10009
#define MAXN 100010
#define MAXM 100010
#define INF 99999999
#define ll __int64
#define bug cout<<"here"<<endl
#define fread freopen("ceshi.txt","r",stdin)
#define fwrite freopen("out.txt","w",stdout)
using namespace std;
int Read()
{
char c = getchar();
while (c < '0' || c > '9') c = getchar();
int x = 0;
while (c >= '0' && c <= '9') {
x = x * 10 + c - '0';
c = getchar();
}
return x;
}
void Print(int a)
{
if(a>9)
Print(a/10);
putchar(a%10+'0');
}
double dp[MAXN];
void init()
{
MEM(dp,0);
for(int i=2;i<MAXN;i++)
{
double tmp=0;
int cnt=0;
for(int j=1;j*j<=i;j++)//j=1 i/j=i 这个时候把dp[i]加进去的时候dp[i]=0 所以是没有的
{
if(i%j==0)
{
cnt++;
tmp+=dp[j];
if(i/j!=j)
{
cnt++;
tmp+=dp[i/j];
}
}
}
dp[i]=(tmp+cnt)/((double)(cnt-1));
}
}
int main()
{
// fread;
int tc;
scanf("%d",&tc);
int cs=1;
init();
while(tc--)
{
int n;
scanf("%d",&n);
printf("Case %d: %.6lf\n",cs++,dp[n]);
}
return 0;
}