码迷,mamicode.com
首页 > 其他好文 > 详细

2015年省赛组队选拔赛3

时间:2015-04-03 00:02:44      阅读:309      评论:0      收藏:0      [点我收藏+]

标签:

Fast Typing

概率DP 求期望,期望一般要逆推dp[i]代表已经正确打完前i个字符并且正确打完剩下的所有字母的期望,so dp[n] = 0,我们要求dp[0],题目让我们求最小,最小是因为他可以打不定字母再

去检测,具体多少不知道,对于dp[i],枚举j代表打了j个字母然后去检查,在枚举k,代表敲的j个字母,第k个是错误的,so对于不同的j,设敲了几个字母再去检查的期望为bj,

则dp[i] = min(b[j]),

其中bj = t+time // t是检查的时间,time是写这j个字符的时间,用前缀和即可

a[i+1]*(dp[i]+j*ts) // 第一个纠错了,因为是敲了j个再去检查,所以按删除键j次,然后就回到了正确打完前i个字符的情况

(1-a[i+1])*(a[i+2])*(dp[i+1]+(j-1)*ts) //第二个错了,回退j-1次,然后就回到了正确打完前i+1个字符的情况

....

(1-a[i+1])*....*(1-a[i+j])*(dp[i+j]) // j个字符全对了

注意等式左右都有dp[i],移项,在除一下就行了

by fd

技术分享
 1     
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <algorithm>
 5 using namespace std;
 6 double dp[111], a[111], b[111];
 7 int main()
 8 {
 9     int n;
10     double t, ts;
11     while(scanf("%d %lf %lf", &n, &t, &ts) != EOF)
12     {
13         for(int i = 1; i <= n; i++)
14             scanf("%lf", &a[i]);
15         for(int i = 1; i <= n; i++)
16         {
17             scanf("%lf", &b[i]);
18             b[i] += b[i-1];
19         }
20         memset(dp, 0, sizeof(dp));
21         for(int i = n-1; i >= 0; i--)
22         {
23             dp[i] = -1;
24             for(int j = 1; j+i <= n; j++)
25             {
26                 double tmp = b[i+j]-b[i]+t+a[i+1]*ts*(j);
27                 double tmp2 = 1;
28                 for(int k = 1; k <= j+1; k++)
29                 {
30                     if(k > 1)
31                     {
32                         if(k == j+1)
33                             tmp += tmp2*(dp[i+k-1]+ts*(j-k+1));
34                         else
35                             tmp += tmp2*a[i+k]*(dp[i+k-1]+ts*(j-k+1));
36                     }
37                     tmp2 *= (1-a[i+k]);
38                 }
39                 if(dp[i] < 0)
40                     dp[i] = tmp/(1-a[i+1]);
41                 else
42                     dp[i] = min(dp[i], tmp/(1-a[i+1]));
43             }
44         }
45         printf("%.2lf\n", dp[0]);
46     }
47     return 0;
48 }
View Code

How Many Ways?

组合数+容斥 看到k很小就要往那里想,首先没有障碍物答案就是C(n+m, n)或C(n+m, m),然后减去不符合的,减去经过一个障碍物的,比如是x,y,那么相当于从0,0到x,y再从x,y到n,m。

然后加上经过2个障碍物的,减去经过3个障碍物的。。。。

by fd

技术分享
  1 #include <cstdio>
  2 #include <cstring>
  3 #include <algorithm>
  4 using namespace std;
  5 typedef __int64 LL;
  6 const LL mod = 19992010;
  7 struct node
  8 {
  9     int x, y;
 10 }p[12];
 11 int n, m, k;
 12 LL prime[2111], vis[2111], c;
 13 LL pow_mod(LL a, LL b)
 14 {
 15     LL ans = 1;
 16     while(b)
 17     {
 18         if(b&1)
 19         {
 20             ans *= a;
 21             ans %= mod;
 22         }
 23         b >>= 1;
 24         a *= a;
 25         a %= mod;
 26     }
 27     return ans;
 28 }
 29 void init()
 30 {
 31     c = 0;
 32     for(int i = 2; i <= 2000; i++)
 33     {
 34         if(!vis[i])
 35         {
 36             prime[c++] = i;
 37             for(int j = i*2; j <= 2000; j += i)
 38                 vis[j] = 1;
 39         }
 40     }
 41 }
 42 LL getnum(LL n, LL p)
 43 {
 44     LL sum = 0;
 45     while(n)
 46     {
 47         sum += n/p;
 48         n /= p;
 49     }
 50     return sum;
 51 }
 52 LL C(LL n, LL m)
 53 {
 54     LL ans = 1;
 55     /*for(int i = 1; i <= m; i++)
 56     {
 57         ans *= (n-i+1);
 58         ans /= i;
 59     }
 60     printf("***%I64d %I64d %I64d ", n, m, ans);
 61     ans = 1;
 62     */
 63     for(int i = 0; i < c && prime[i] <= n; i++)
 64     {
 65         LL x = getnum(n, prime[i]);
 66         LL y = getnum(n-m, prime[i]);
 67         LL z = getnum(m, prime[i]);
 68         ans *= pow_mod(prime[i], x-y-z);
 69         ans %= mod;
 70     }
 71     return ans;
 72 }
 73 
 74 bool cmp(node a, node b)
 75 {
 76     if(a.x != b.x)
 77         return a.x < b.x;
 78     return a.y < b.y;
 79 }
 80 
 81 void dfs(int i, int j, LL num, LL& ans, int cnt)
 82 {
 83     if(i == k+1)
 84     {
 85         if(cnt)
 86         {
 87             if(cnt&1)
 88             {
 89                 ans -= num*C(p[i].x-p[j].x+p[i].y-p[j].y, p[i].x-p[j].x)%mod;
 90                 if(ans < 0)
 91                     ans += mod;
 92             }
 93             else
 94             {
 95                 ans += num*C(p[i].x-p[j].x+p[i].y-p[j].y, p[i].x-p[j].x)%mod;
 96                 ans %= mod;
 97                 if(ans < 0)
 98                     ans += mod;
 99             }
100         }
101         return;
102     }
103     if(p[i].x >= p[j].x && p[i].y >= p[j].y)
104     {
105         LL tmp = C(p[i].x-p[j].x+p[i].y-p[j].y, p[i].x-p[j].x)*num%mod;
106         dfs(i+1, i, tmp, ans, cnt+1);
107     }
108     dfs(i+1, j, num, ans, cnt);
109 }
110 int main()
111 {
112     init();
113     int T;
114     scanf("%d", &T);
115     while(T--)
116     {
117         
118         scanf("%d %d %d", &n, &m, &k);
119         for(int i = 1; i <= k; i++)
120         {
121             scanf("%d %d", &p[i].x, &p[i].y);
122         }
123         sort(p, p+k+1, cmp);
124         p[0].x = 0;
125         p[0].y = 0;
126         p[k+1].x = n;
127         p[k+1].y = m;
128         LL ans = C(n+m, n);
129         dfs(1, 0, 1, ans, 0);
130         printf("%I64d\n", ans);
131     }
132     return 0;
133 }
134 /*
135 5
136 1000 1000 5
137 1 1
138 2 2
139 5 5
140 100 100
141 98 555
142 
143 1000 1000 4
144 1 1
145 5 5
146 100 100
147 98 555
148 */
View Code

Mine Sweeping

枚举 DP当然可以搞,后来想到一中简单方法,枚举前2个位置有没有地雷,然后检测是否可行,答案最多4中,因为前面2个位置确定了,下面第二个位置雷的数量等于上面3个位置雷的数量之和,即x1+x2+x3 = y2,x1,x2是枚举的已经确定了,所以x3也确定了,然后x2和x3和y3推x4,推到最后,有矛盾退出。。

by fd

 

2015年省赛组队选拔赛3

标签:

原文地址:http://www.cnblogs.com/tzcacm/p/4388619.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!