zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    图像功率结合
    三星(多星)模型
    双星模型
    卫星变轨问题
    桌面木块弹簧
    球——绳模型、球——杆模型
    汽车拐弯问题
    圆锥摆模型
    省队集训日记
    NOI前比赛经验总结
  • 原文地址:https://www.cnblogs.com/cdyboke/p/4856943.html
Copyright © 2011-2022 走看看