bestcoder Round #7 前三题题解
BestCoder Round #7
Contest Type : Register Public Contest Status : Ended
Current Server Time : 2014-08-31 21:12:12
Solved | Pro.ID | Title | Ratio(Accepted / Submitted) |
---|---|---|---|
1001 | Little Pony and Permutation | 37.91%(348/918) | |
1002 | Little Pony and Alohomora Part I | 29.86%(132/442) | |
1003 | Little Pony and Dice | 20.00%(8/40) | |
1004 | Little Pony and Boast Busters | 4.41%(3/68) |
hdu4985 | Little Pony and Permutation | 73.23%(93/127) | |
hdu4986 | Little Pony and Alohomora Part I | 61.11%(88/144) | |
hdu4987 | Little Pony and Dice | 23.53%(36/153) | |
hdu4988 | Little Pony and Boast Busters | 80.00%(16/20) |
1001( hdu4985 Little Pony and Permutation ):
题意:给出一些那样的映射,把每个环放到括号里输出。
题解:直接搞,超水,看代码:
代码:
1 //#pragma comment(linker, "/STACK:102400000,102400000") 2 #include<cstdio> 3 #include<cmath> 4 #include<iostream> 5 #include<cstring> 6 #include<algorithm> 7 #include<cmath> 8 #include<map> 9 #include<set> 10 #include<stack> 11 #include<queue> 12 using namespace std; 13 #define ll long long 14 #define usll unsigned ll 15 #define mz(array) memset(array, 0, sizeof(array)) 16 #define minf(array) memset(array, 0x3f, sizeof(array)) 17 #define REP(i,n) for(i=0;i<(n);i++) 18 #define FOR(i,x,n) for(i=(x);i<=(n);i++) 19 #define RD(x) scanf("%d",&x) 20 #define RD2(x,y) scanf("%d%d",&x,&y) 21 #define RD3(x,y,z) scanf("%d%d%d",&x,&y,&z) 22 #define WN(x) printf("%d\n",x); 23 #define RE freopen("D.in","r",stdin) 24 #define WE freopen("1biao.out","w",stdout) 25 #define mp make_pair 26 #define pb push_back 27 const int maxn=111111; 28 int n; 29 int a[maxn]; 30 int b[maxn]; 31 int main() { 32 int i,j; 33 while(scanf("%d",&n)!=EOF) { 34 FOR(i,1,n)scanf("%d",&a[i]); 35 mz(b); 36 FOR(i,1,n) { 37 if(!b[i]) { 38 printf("(%d",i); 39 j=a[i]; 40 while(j!=i) { 41 printf(" %d",j); 42 b[j]=1; 43 j=a[j]; 44 } 45 putchar(')'); 46 } 47 48 } 49 puts(""); 50 } 51 return 0; 52 }
(有人说用递归会爆栈,太萎了,看我的碉递归版:
1 //#pragma comment(linker, "/STACK:102400000,102400000") 2 #include<cstdio> 3 #include<cmath> 4 #include<iostream> 5 #include<cstring> 6 #include<algorithm> 7 #include<cmath> 8 #include<map> 9 #include<set> 10 #include<stack> 11 #include<queue> 12 using namespace std; 13 #define ll long long 14 #define usll unsigned ll 15 #define mz(array) memset(array, 0, sizeof(array)) 16 #define minf(array) memset(array, 0x3f, sizeof(array)) 17 #define REP(i,n) for(i=0;i<(n);i++) 18 #define FOR(i,x,n) for(i=(x);i<=(n);i++) 19 #define RD(x) scanf("%d",&x) 20 #define RD2(x,y) scanf("%d%d",&x,&y) 21 #define RD3(x,y,z) scanf("%d%d%d",&x,&y,&z) 22 #define WN(x) printf("%d\n",x); 23 #define RE freopen("D.in","r",stdin) 24 #define WE freopen("1biao.out","w",stdout) 25 #define mp make_pair 26 #define pb push_back 27 const int maxn=111111; 28 int n; 29 int a[maxn]; 30 int b[maxn]; 31 int i,j; 32 33 void dg(const int &x){ 34 if(x==i)return; 35 printf(" %d",x); 36 b[x]=1; 37 dg(a[x]); 38 } 39 40 int main() { 41 while(scanf("%d",&n)!=EOF) { 42 FOR(i,1,n)scanf("%d",&a[i]); 43 mz(b); 44 FOR(i,1,n) { 45 if(!b[i]) { 46 printf("(%d",i); 47 dg(a[i]); 48 putchar(')'); 49 } 50 51 } 52 puts(""); 53 } 54 return 0; 55 }
1002( hdu4986 Little Pony and Alohomora Part I):
题意:随机出一个元素个数为n的1001的输入,求1001的输出的括号对 的个数的期望值。
题解:找规律,分类,近似解
先暴力搞出每种1001的输入,算期望,发现N为一位数的时候后面都算不快了,不过我们得到了前几个数据。
观察数据,可以发现ans(n)=1/1 + 1/2 + 1/3 + ... + 1/n
这个是调和级数!没有超碉公式能算。
不过n大的时候有近似公式,ans(n)约等于 ln(n)+0.57721566490153286060651209
于是我们就数少的时候暴力算,数大的时候用这个约等于的来算。
注意暴力算的时候从1/n加到1,由于浮点数的性质,这样精度比较高。
(其实这个约等于的和暴力算得的有好多数不一样,暴力算的因为精度有限也可能不对。如果要全部输出暴力的结果,可以分段打表,隔一段记一个数,输入n在两段之间时,从上一段记的那个数开始算)
代码:
1 //#pragma comment(linker, "/STACK:102400000,102400000") 2 #include<cstdio> 3 #include<cmath> 4 #include<iostream> 5 #include<cstring> 6 #include<algorithm> 7 #include<cmath> 8 #include<map> 9 #include<set> 10 #include<stack> 11 #include<queue> 12 using namespace std; 13 #define ll long long 14 #define usll unsigned ll 15 #define mz(array) memset(array, 0, sizeof(array)) 16 #define minf(array) memset(array, 0x3f, sizeof(array)) 17 #define REP(i,n) for(i=0;i<(n);i++) 18 #define FOR(i,x,n) for(i=(x);i<=(n);i++) 19 #define RD(x) scanf("%d",&x) 20 #define RD2(x,y) scanf("%d%d",&x,&y) 21 #define RD3(x,y,z) scanf("%d%d%d",&x,&y,&z) 22 #define WN(x) printf("%d\n",x); 23 #define RE freopen("D.in","r",stdin) 24 #define WE freopen("1biao.out","w",stdout) 25 #define mp make_pair 26 #define pb push_back 27 28 double farm(int n) { 29 double re=0.0; 30 for(int i=n; i>=1; i--) { 31 re+=1.0/i; 32 } 33 return re; 34 } 35 36 int main() { 37 int i,j; 38 int n; 39 while(scanf("%d",&n)!=EOF) { 40 if(n<=10000) {///8个0交C++能984ms过,4个0能过 41 double t=farm(n); 42 printf("%.4f\n",t); 43 } else 44 printf("%.4f\n",log((double)n)+0.5772156649);///实际上10035就不一样了,不过数据里没有 45 //getchar(); 46 } 47 return 0; 48 }
1003( hdu4987 Little Pony and Dice ):
题意:大富翁!地图有0~n这些格子,从0开始扔骰子走,骰子有m面,标有1~m。当人到达n或者超过n就结束。求在n结束的概率。(1<= n,m <=10^9)
题解:DP+特判。
f[i]表示到第i个格子的概率,s[i]表示0~i的概率和。
则f[i]=s[i-1]-s[i-1-m]
这样O(n)就能算,但是n<=10^9,光这样算还不行。
再次找规律,发现n大的时候,后面的f[i]会全是一样的数,那么我们遇到连续若干个一样的数,就可以把它当做解了。“一样”我用差小于10^-9来判,连续2000个一样。
这样能过初审了,但是会被hack,system test也过不去,可能是因为m超大的时候很多小数加起来,精度不够。
固定m,则n=m时答案最大。当m=555555时,答案最大也为0,则m>=555555就直接答案为0。加上这个就能过了。
还有一个特判,是n<=m时能直接一个公式求得答案,公式推导我写在代码的注释里了。
代码:
1 //#pragma comment(linker, "/STACK:102400000,102400000") 2 #include<cstdio> 3 #include<cmath> 4 #include<iostream> 5 #include<cstring> 6 #include<algorithm> 7 #include<cmath> 8 #include<map> 9 #include<set> 10 #include<stack> 11 #include<queue> 12 using namespace std; 13 #define ll long long 14 #define usll unsigned ll 15 #define mz(array) memset(array, 0, sizeof(array)) 16 #define minf(array) memset(array, 0x3f, sizeof(array)) 17 #define REP(i,n) for(i=0;i<(n);i++) 18 #define FOR(i,x,n) for(i=(x);i<=(n);i++) 19 #define RD(x) scanf("%d",&x) 20 #define RD2(x,y) scanf("%d%d",&x,&y) 21 #define RD3(x,y,z) scanf("%d%d%d",&x,&y,&z) 22 #define WN(x) printf("%d\n",x); 23 #define RE freopen("D.in","r",stdin) 24 #define WE freopen("1biao.out","w",stdout) 25 #define mp make_pair 26 #define pb push_back 27 const int maxcul=1111111; 28 const int maxcnt=2000; 29 const double eps=1e-9; 30 31 double f[maxcul+10]; 32 double s[maxcul+10]; 33 double farm(int m,int n){ 34 if(m>555555)return 0.0;/// m固定,当n=m时ans取最大值,m大于这个时最大值也是0 35 if (n<=m) return pow(1.0+1.0/m,n-1)/m; 36 /// C(n-1,0)/m + C(n-1,1)/m/m + C(n-1,2)/m/m/m + ... + C(n-1,n-1)/(m^n) 37 ///=( C(n-1,0) + C(n-1,1)/m + C(n-1,2)/m/m + ... + C(n-1,n-1)/(m^(n-1)) )/m 38 ///=(1+1/m)^(n-1)/m 39 int i,j; 40 int cnt=1; 41 mz(f); 42 f[0]=1.0; 43 s[0]=1.0; 44 for(i=1;i<=n;i++){ 45 int minj=max(0,i-m); 46 if(minj==0) f[i] = s[i-1]/m; 47 else f[i] = (s[i-1] - s[minj-1]) / m; 48 s[i]=f[i]+s[i-1]; 49 if(i>m && fabs(f[i]-f[i-1])<eps)cnt++; 50 else cnt=1; 51 if(cnt>maxcnt)break; 52 } 53 if(cnt>maxcnt) return f[i]; 54 else return f[n]; 55 } 56 57 int main() { 58 int i,j; 59 int m,n; 60 while(scanf("%d%d",&m,&n)!=EOF){ 61 printf("%.5f\n",farm(m,n)); 62 } 63 return 0; 64 }