UVA 10759 Dice Throwing

  题意为抛n个骰子凑成的点数和大于或等于x的概率,刚开始用暴力枚举,虽然AC了,但时间为2.227s,然后百度了下别人的做法,交了一遍,靠,0.000s,然后看了下思路,原来是dp,在暴力的基础上记忆化搜索,把所有可能枚举出来再累加,然后自己也打了一遍,0.000sA了,做法是开一个二维数组,第一维是骰子个数,第二维是和x,然后一个只有可能是1,2,3,4,5,6,倒两个骰子时是1+1,2,3,4,5,6     2+1,2,3,4,5,6  3+...累加向上推即可

  1 //暴力做法,2.227s
  2 #include<cstdio>
  3 #include<cmath>
  4 #include<iostream>
  5 #include<cstring>
  6 
  7 using namespace std;
  8 
  9 typedef long long ll;
 10 
 11 int n,x,dice[7],prime[10]={2,3,5,7,11,13,17,19,23},fact[30][10];//n个dice,x为和,dice[i]点数为i的骰子个数
 12 ll fz,fm;
 13 
 14 void fact_table()//fact[i] i!的质因分解表
 15 {
 16     memset(fact,0,sizeof(fact));
 17     for(int i=2;i<=24;i++)
 18     {
 19         int x=i;
 20         for(int j=0;x>=prime[j]&&j<9;j++)
 21             while(x%prime[j]==0)
 22             {
 23                 fact[i][j]++;
 24                 x/=prime[j];
 25             }
 26     }
 27     for(int i=3;i<=24;i++)
 28     {
 29         for(int j=0;j<9;j++)
 30             fact[i][j]+=fact[i-1][j];
 31     }
 32 }
 33 
 34 void A6n()//dice[1]个1,dice[2]个2...时的种数=n!/(dice[1]!*dice[2]!*dice[3]!*dice[4]!*dice[5]!*dice[6]!)
 35 {
 36     ll x=1;
 37         int fn[10],fnum[10];
 38     memcpy(fn,fact[n],sizeof(fn));
 39     for(int i=1;i<=6;i++)//n!/dice[i]!
 40     {
 41         memcpy(fnum,fact[dice[i]],sizeof(fnum));
 42         for(int j=0;j<9;j++)
 43             fn[j]-=fnum[j];
 44     }
 45     for(int i=0;i<9;i++)
 46         x*=pow(prime[i],fn[i]);
 47         /*for(int i=1;i<=6;i++)
 48                 printf("%d ",dice[i]);
 49         puts("");*/
 50     fz+=x;//累加倒分子
 51 }
 52 
 53 void C6n(int u,int n,int sum)//枚举所有可能
 54 {
 55     if(u==6)
 56     {
 57             dice[u]=n;
 58                 sum+=u*n;
 59         if(sum>=x) A6n();//和大于或等于x就加到分子中
 60         return;
 61     }
 62     for(int i=0;i<=n;i++)
 63     {
 64         dice[u]=i;
 65         C6n(u+1,n-i,sum+i*u);
 66     }
 67 }
 68 
 69 void slove()
 70 {
 71     if(6*n<x)
 72     {
 73         puts("0");
 74         return;
 75     }
 76     fz=0;
 77     C6n(1,n,0);
 78     int e2,e3;
 79     e2=e3=n;//6^n=2^e2*2^e3
 80         //printf("fz=%lld
",fz);
 81     while(fz%2==0)
 82     {
 83         fz>>=1;
 84         e2--;
 85         if(!e2) break;//e2==0时要break掉,不然变成2的负数次方会wa
 86     }
 87     while(fz%3==0)
 88     {
 89         fz/=3;
 90         e3--;
 91         if(!e3) break;
 92     }
 93         //printf("fz=%lld e2=%d e3=%d
",fz,e2,e3);
 94     fm=pow(3,e3)*pow(2,e2);
 95     if(fz==0) puts("0");
 96     else if(fm==1) puts("1");
 97     else printf("%lld/%lld
",fz,fm);
 98 }
 99 
100 int main()
101 {
102     //freopen("/home/user/桌面/in","r",stdin);
103     fact_table();
104     while(scanf("%d%d",&n,&x)==2&&(n||x))
105                 slove();
106     return 0;
107 }
View Code
 1 #include<cstdio>
 2 #include<cmath>
 3 #include<iostream>
 4 #include<cstring>
 5 
 6 using namespace std;
 7 
 8 typedef long long ll;
 9 
10 int n,x;//n个dice,x为和
11 ll fz,fm,fact[30][155];
12 
13 void fact_table()
14 {
15     memset(fact,0,sizeof(fact));
16     for(int i=1;i<=6;i++)
17         fact[1][i]=1;
18     for(int i=2;i<=24;i++)//fact[i][j]表示i个骰子和为j的种数
19         for(int j=1;j<=6;j++)
20             for(int k=i-1;k<=(i-1)*6;k++)
21                 fact[i][k+j]+=fact[i-1][k];
22     /*for(int i=1;i<=24;i++)
23     {
24         printf("%d: ",i);
25         for(int j=i;j<i*6;j++)
26             printf("%lld ",fact[i][j]);
27         printf("
");
28     }*/
29 }
30 void slove()
31 {
32     int e2=n,e3=n;
33     fz=0;
34     for(int i=x;i<=150;i++)
35         fz+=fact[n][i];
36     while(fz%2==0)
37     {
38         fz>>=1;
39         e2--;
40         if(!e2) break;
41     }
42     while(fz%3==0)
43     {
44         fz/=3;
45         e3--;
46         if(!e3) break;
47     }
48     fm=pow(3,e3)*pow(2,e2);
49     if(fz==0) puts("0");
50     else if(fm==1) puts("1");
51     else printf("%lld/%lld
",fz,fm);
52 }
53 
54 int main()
55 {
56     //freopen("in","r",stdin);
57     fact_table();
58     while(scanf("%d%d",&n,&x)==2&&(n||x)) slove();
59     return 0;
60 }
View Code
原文地址:https://www.cnblogs.com/cdyboke/p/4856943.html