Cut the Cake
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 300 Accepted Submission(s): 135
Problem Description MMM got a big big big cake, and invited all her M friends to eat the cake together. Surprisingly one of her friends HZ took some (N) strawberries which MMM likes very much to decorate the cake (of course they also eat strawberries, not just for decoration). HZ is in charge of the decoration, and he thinks that it’s not a big deal that he put the strawberries on the cake randomly one by one. After that, MMM would cut the cake into M pieces of sector with equal size and shape (the last one came to the party will have no cake to eat), and choose one piece first. MMM wants to know the probability that she can get all N strawberries, can you help her? As the cake is so big, all strawberries on it could be treat as points.
Input First line is the integer T, which means there are T cases.
For each case, two integers M, N indicate the number of her friends and the number of strawberry.
(2 < M, N <= 20, T <= 400)
Output As the probability could be very small, you should output the probability in the form of a fraction in lowest terms. For each case, output the probability in a single line. Please see the sample for more details.
Sample Input 2 3 3 3 4
Sample Output 1/3 4/27
Source
2013 ACM/ICPC Asia Regional Changchun Online
Recommend liuyiding
题目意思很容易看懂。
公式就是 n / (m^(n-1))
这个结果可以积分求得。
枚举两个点,位于两边,就是P(n,2) = n*(n-1)
然后两个点形成的角度范围在 0~1/m之间。剩下n-2个点放的概率就是 x^(n-2)
所以积分 从0~1/m x^(n-2) 对x进行积分。积分结果乘上n*(n-1)
要用高精度。
一种是C++ 完全高精度模板,积攒到最后一场网络赛终于用上了,一用就是两题,哈哈。
但是还是JAVA写起来爽,简单
C++版:
1 /* *********************************************** 2 Author :kuangbin 3 Created Time :2013/9/28 星期六 12:54:45 4 File Name :2013长春网络赛\1004.cpp 5 ************************************************ */ 6 7 #pragma comment(linker, "/STACK:1024000000,1024000000") 8 #include <stdio.h> 9 #include <string.h> 10 #include <iostream> 11 #include <algorithm> 12 #include <vector> 13 #include <queue> 14 #include <set> 15 #include <map> 16 #include <string> 17 #include <math.h> 18 #include <stdlib.h> 19 #include <time.h> 20 using namespace std; 21 /* 22 * 完全大数模板 23 * 输出cin>>a 24 * 输出a.print(); 25 * 注意这个输入不能自动去掉前导0的,可以先读入到char数组,去掉前导0,再用构造函数。 26 */ 27 #define MAXN 9999 28 #define MAXSIZE 1010 29 #define DLEN 4 30 31 class BigNum 32 { 33 private: 34 int a[500]; //可以控制大数的位数 35 int len; 36 public: 37 BigNum(){len=1;memset(a,0,sizeof(a));} //构造函数 38 BigNum(const int); //将一个int类型的变量转化成大数 39 BigNum(const char*); //将一个字符串类型的变量转化为大数 40 BigNum(const BigNum &); //拷贝构造函数 41 BigNum &operator=(const BigNum &); //重载赋值运算符,大数之间进行赋值运算 42 friend istream& operator>>(istream&,BigNum&); //重载输入运算符 43 friend ostream& operator<<(ostream&,BigNum&); //重载输出运算符 44 45 BigNum operator+(const BigNum &)const; //重载加法运算符,两个大数之间的相加运算 46 BigNum operator-(const BigNum &)const; //重载减法运算符,两个大数之间的相减运算 47 BigNum operator*(const BigNum &)const; //重载乘法运算符,两个大数之间的相乘运算 48 BigNum operator/(const int &)const; //重载除法运算符,大数对一个整数进行相除运算 49 50 BigNum operator^(const int &)const; //大数的n次方运算 51 int operator%(const int &)const; //大数对一个int类型的变量进行取模运算 52 bool operator>(const BigNum &T)const; //大数和另一个大数的大小比较 53 bool operator>(const int &t)const; //大数和一个int类型的变量的大小比较 54 55 void print(); //输出大数 56 }; 57 BigNum::BigNum(const int b) //将一个int类型的变量转化为大数 58 { 59 int c,d=b; 60 len=0; 61 memset(a,0,sizeof(a)); 62 while(d>MAXN) 63 { 64 c=d-(d/(MAXN+1))*(MAXN+1); 65 d=d/(MAXN+1); 66 a[len++]=c; 67 } 68 a[len++]=d; 69 } 70 BigNum::BigNum(const char *s) //将一个字符串类型的变量转化为大数 71 { 72 int t,k,index,L,i; 73 memset(a,0,sizeof(a)); 74 L=strlen(s); 75 len=L/DLEN; 76 if(L%DLEN)len++; 77 index=0; 78 for(i=L-1;i>=0;i-=DLEN) 79 { 80 t=0; 81 k=i-DLEN+1; 82 if(k<0)k=0; 83 for(int j=k;j<=i;j++) 84 t=t*10+s[j]-'0'; 85 a[index++]=t; 86 } 87 } 88 BigNum::BigNum(const BigNum &T):len(T.len) //拷贝构造函数 89 { 90 int i; 91 memset(a,0,sizeof(a)); 92 for(i=0;i<len;i++) 93 a[i]=T.a[i]; 94 } 95 BigNum & BigNum::operator=(const BigNum &n) //重载赋值运算符,大数之间赋值运算 96 { 97 int i; 98 len=n.len; 99 memset(a,0,sizeof(a)); 100 for(i=0;i<len;i++) 101 a[i]=n.a[i]; 102 return *this; 103 } 104 istream& operator>>(istream &in,BigNum &b) 105 { 106 char ch[MAXSIZE*4]; 107 int i=-1; 108 in>>ch; 109 int L=strlen(ch); 110 int count=0,sum=0; 111 for(i=L-1;i>=0;) 112 { 113 sum=0; 114 int t=1; 115 for(int j=0;j<4&&i>=0;j++,i--,t*=10) 116 { 117 sum+=(ch[i]-'0')*t; 118 } 119 b.a[count]=sum; 120 count++; 121 } 122 b.len=count++; 123 return in; 124 } 125 ostream& operator<<(ostream& out,BigNum& b) //重载输出运算符 126 { 127 int i; 128 cout<<b.a[b.len-1]; 129 for(i=b.len-2;i>=0;i--) 130 { 131 printf("%04d",b.a[i]); 132 } 133 return out; 134 } 135 BigNum BigNum::operator+(const BigNum &T)const //两个大数之间的相加运算 136 { 137 BigNum t(*this); 138 int i,big; 139 big=T.len>len?T.len:len; 140 for(i=0;i<big;i++) 141 { 142 t.a[i]+=T.a[i]; 143 if(t.a[i]>MAXN) 144 { 145 t.a[i+1]++; 146 t.a[i]-=MAXN+1; 147 } 148 } 149 if(t.a[big]!=0) 150 t.len=big+1; 151 else t.len=big; 152 return t; 153 } 154 BigNum BigNum::operator-(const BigNum &T)const //两个大数之间的相减运算 155 { 156 int i,j,big; 157 bool flag; 158 BigNum t1,t2; 159 if(*this>T) 160 { 161 t1=*this; 162 t2=T; 163 flag=0; 164 } 165 else 166 { 167 t1=T; 168 t2=*this; 169 flag=1; 170 } 171 big=t1.len; 172 for(i=0;i<big;i++) 173 { 174 if(t1.a[i]<t2.a[i]) 175 { 176 j=i+1; 177 while(t1.a[j]==0) 178 j++; 179 t1.a[j--]--; 180 while(j>i) 181 t1.a[j--]+=MAXN; 182 t1.a[i]+=MAXN+1-t2.a[i]; 183 } 184 else t1.a[i]-=t2.a[i]; 185 } 186 t1.len=big; 187 while(t1.a[len-1]==0 && t1.len>1) 188 { 189 t1.len--; 190 big--; 191 } 192 if(flag) 193 t1.a[big-1]=0-t1.a[big-1]; 194 return t1; 195 } 196 BigNum BigNum::operator*(const BigNum &T)const //两个大数之间的相乘 197 { 198 BigNum ret; 199 int i,j,up; 200 int temp,temp1; 201 for(i=0;i<len;i++) 202 { 203 up=0; 204 for(j=0;j<T.len;j++) 205 { 206 temp=a[i]*T.a[j]+ret.a[i+j]+up; 207 if(temp>MAXN) 208 { 209 temp1=temp-temp/(MAXN+1)*(MAXN+1); 210 up=temp/(MAXN+1); 211 ret.a[i+j]=temp1; 212 } 213 else 214 { 215 up=0; 216 ret.a[i+j]=temp; 217 } 218 } 219 if(up!=0) 220 ret.a[i+j]=up; 221 } 222 ret.len=i+j; 223 while(ret.a[ret.len-1]==0 && ret.len>1)ret.len--; 224 return ret; 225 } 226 BigNum BigNum::operator/(const int &b)const //大数对一个整数进行相除运算 227 { 228 BigNum ret; 229 int i,down=0; 230 for(i=len-1;i>=0;i--) 231 { 232 ret.a[i]=(a[i]+down*(MAXN+1))/b; 233 down=a[i]+down*(MAXN+1)-ret.a[i]*b; 234 } 235 ret.len=len; 236 while(ret.a[ret.len-1]==0 && ret.len>1) 237 ret.len--; 238 return ret; 239 } 240 int BigNum::operator%(const int &b)const //大数对一个 int类型的变量进行取模 241 { 242 int i,d=0; 243 for(i=len-1;i>=0;i--) 244 d=((d*(MAXN+1))%b+a[i])%b; 245 return d; 246 } 247 BigNum BigNum::operator^(const int &n)const //大数的n次方运算 248 { 249 BigNum t,ret(1); 250 int i; 251 if(n<0)exit(-1); 252 if(n==0)return 1; 253 if(n==1)return *this; 254 int m=n; 255 while(m>1) 256 { 257 t=*this; 258 for(i=1;(i<<1)<=m;i<<=1) 259 t=t*t; 260 m-=i; 261 ret=ret*t; 262 if(m==1)ret=ret*(*this); 263 } 264 return ret; 265 } 266 bool BigNum::operator>(const BigNum &T)const //大数和另一个大数的大小比较 267 { 268 int ln; 269 if(len>T.len)return true; 270 else if(len==T.len) 271 { 272 ln=len-1; 273 while(a[ln]==T.a[ln]&&ln>=0) 274 ln--; 275 if(ln>=0 && a[ln]>T.a[ln]) 276 return true; 277 else 278 return false; 279 } 280 else 281 return false; 282 } 283 bool BigNum::operator>(const int &t)const //大数和一个int类型的变量的大小比较 284 { 285 BigNum b(t); 286 return *this>b; 287 } 288 void BigNum::print() //输出大数 289 { 290 int i; 291 printf("%d",a[len-1]); 292 for(i=len-2;i>=0;i--) 293 printf("%04d",a[i]); 294 printf("\n"); 295 } 296 297 int main() 298 { 299 //freopen("in.txt","r",stdin); 300 //freopen("out.txt","w",stdout); 301 int m,n; 302 int T; 303 scanf("%d",&T); 304 while(T--) 305 { 306 scanf("%d%d",&m,&n); 307 BigNum tt = 1; 308 for(int i = 1;i < n;i++) 309 tt = tt*m; 310 int tmp = n; 311 for(int i = 2;i <= n;i++) 312 { 313 while( tmp%i == 0 && (tt%i == 0) ) 314 { 315 tmp /= i; 316 tt = tt/i; 317 } 318 } 319 printf("%d/",tmp); 320 tt.print(); 321 322 } 323 return 0; 324 }
View Code
JAVA
1 import java.io.*; 2 import java.math.*; 3 import java.util.*; 4 5 public class Main { 6 static BigInteger gcd(BigInteger a,BigInteger b) 7 { 8 if(b.equals(BigInteger.ZERO))return a; 9 else return gcd(b,a.mod(b)); 10 } 11 public static void main(String arg[]) 12 { 13 int T; 14 int n,m; 15 Scanner cin = new Scanner(System.in); 16 T = cin.nextInt(); 17 while( T > 0 ) 18 { 19 m = cin.nextInt(); 20 n = cin.nextInt(); 21 BigInteger tmp1 = BigInteger.valueOf(n); 22 BigInteger tmp2 = BigInteger.valueOf(m).pow(n-1); 23 BigInteger tt = gcd(tmp1,tmp2); 24 tmp1 = tmp1.divide(tt); 25 tmp2 = tmp2.divide(tt); 26 System.out.println(tmp1+"/"+tmp2); 27 T--; 28 } 29 } 30 }
View Code