方法:
设ans[i][j]表示i个骰子点数恰好为j的概率。那么ans[1][1]到ans[1][6]都为1/6。
显然,$ans[i][j]=sum{ans[i-1][j-k]}(1<=k<=6,j>k)$
n和x上限很小,直接处理出所有点数恰好为某个值的结果,然后再做一遍类似前缀和的东西处理出所有点数大于等于某个值的结果。这里答案需要分数,于是乱写了一个分数结构体。
分数运算(没有优化的):
初始化空的分数:分子为0,分母为1
加法:先通分,然后加分子,然后约分
乘法:先互相约分,然后分子分母分别相乘
错误次数:1次
错误原因:由于把前缀和的范围限制与原数据的范围限制搞混,66行>=0写成>=i,导致WA
1 #include<cstdio> 2 typedef long long LL; 3 LL gcd(LL a,LL b) 4 { 5 LL t; 6 while(b!=0) 7 { 8 t=a; 9 a=b; 10 b=t%b; 11 } 12 return a; 13 } 14 struct X 15 { 16 LL a,b; 17 X() 18 { 19 a=0;b=1; 20 } 21 X(int x,int y) 22 { 23 a=x;b=y; 24 } 25 X operator+(const X& c) 26 { 27 X ans; 28 LL tmp=gcd(b,c.b); 29 ans.b=b/tmp*c.b; 30 ans.a=ans.b/b*a+ans.b/c.b*c.a; 31 tmp=gcd(ans.a,ans.b); 32 ans.a/=tmp; 33 ans.b/=tmp; 34 return ans; 35 } 36 X operator*(const X& c) 37 { 38 LL tmp1=gcd(a,c.b),tmp2=gcd(b,c.a); 39 X ans; 40 ans.a=a/tmp1*c.a/tmp2; 41 ans.b=b/tmp2*c.b/tmp1; 42 return ans; 43 } 44 void print() 45 { 46 if(b==1) 47 printf("%lld",a); 48 else 49 printf("%lld/%lld",a,b); 50 } 51 }ans[26][151],ans2[26][151]; 52 LL T,TT,n,x; 53 int main() 54 { 55 int i,j,k; 56 for(i=1;i<=6;i++) 57 ans[1][i]=(X){1,6}; 58 for(i=2;i<=25;i++) 59 for(j=i;j<=6*i;j++) 60 for(k=1;k<=6;k++) 61 if(j-k>0) 62 ans[i][j]=ans[i][j]+ans[i-1][j-k]*ans[1][1];//ans[1][1]就是1/6 63 for(i=1;i<=25;i++) 64 { 65 ans2[i][6*i]=ans[i][6*i]; 66 for(j=6*i-1;j>=0;j--) 67 ans2[i][j]=ans2[i][j+1]+ans[i][j]; 68 } 69 scanf("%lld",&T); 70 for(TT=1;TT<=T;TT++) 71 { 72 scanf("%lld%lld",&n,&x); 73 printf("Case %lld: ",TT); 74 ans2[n][x].print(); 75 puts(""); 76 } 77 return 0; 78 }