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

第10章例题(紫书)

时间:2016-05-31 23:48:52      阅读:268      评论:0      收藏:0      [点我收藏+]

标签:

21/21

题目都很基础,有很多题书上讲得比较详细,然后隔得时间有点久,所以具体什么trick都忘了,思路也懒得去回忆,所以将就着放上来了。。。。

 

例题10–1 Uva 11582

题意:输入a, b, n让你计算F[a^b]%n;其中这个F[i]是斐波那契数;

题解:

这题是快速幂+找循环节,用什么方法找循环节呢?因为第一个数是0和1,然后当再出现0和1的时候就是出现循环节的时候,然后假如找到了循环节T,然后就有F[n] = F[n % T],预处理找循环节,O(一百万左右),快速幂logn * 10000组数据,复杂度并不高;最后一个注意:给佳哥坑了,f(0)= 0, f(1) = 1;书上写错了。

 

技术分享
 1 /*zhen hao*/
 2 #include <bits/stdc++.h>
 3 using namespace std;
 4 
 5 typedef unsigned long long ull;
 6 const int maxn = 1001;
 7 int F[maxn][maxn * 6], len[maxn];
 8 
 9 void pre_slove() {
10   for (int n = 2; n <= 1000; n++) {
11     F[n][0] = 0; F[n][1] = 1;
12     for (int i = 2; ; i++) {
13       F[n][i] = (F[n][i - 1] + F[n][i - 2]) % n;
14       if (F[n][i - 1] == 0 && F[n][i] == 1) {
15         len[n] = i - 1; break;
16       }
17     }
18   }
19 }
20 
21 int quick(ull a, ull b, ull mod) {
22   int ret = 1;
23   a %= mod;
24   while (b) {
25     if (b & 1) ret = ret * a % mod;
26     b = b / 2;
27     a = a * a % mod;
28   }
29   return ret;
30 }
31 
32 int main() {
33   //freopen("case.in", "r", stdin);
34   pre_slove();
35   int T;
36   scanf("%d", &T);
37   while (T--) {
38     ull a, b;
39     int n;
40     cin >> a >> b >> n;
41     if (n == 1) { puts("0"); continue; }
42     printf("%d\n", F[n][quick(a, b, ull(len[n]))]);
43   }
44   return 0;
45 }
代码君

 

例题10-2 uva12169

题意:给你n个数,这n个数是x1,x3,……,x2*n-1,是由递推式子xi = (xi-1 * a + b) % 10001得到的,现在让你输出一组可能的x2……x2n;

题解:先要确定的是a和b都可以是0~10001,有模运算可知,然后就是枚举a,然后根据式子:

x2 = (x1 * a + b) % n;

x3 = (x2 * a + b) % n;

化简可得:

b * (a + 1) - k * n = x3 - x1 * a ^ 2;

这个类似ax + by = c的形式,可以用扩展欧几里得算法求出b和k,b的范围可以化简到0~n-1,然后判定是不是可行解,然后输出即可。

 

技术分享
 1 /*zhen hao*/
 2 #include <bits/stdc++.h>
 3 using namespace std;
 4 
 5 typedef long long ll;
 6 const int maxn = 1e4 + 100;
 7 const int mod = 1e4 + 1;
 8 int v[maxn];
 9 
10 void gcd(ll a, ll b, ll& d, ll& x, ll& y) {
11   if (!b) { d = a; x = 1; y = 0; }
12   else {
13     gcd(b, a % b, d, y, x); y -= x * (a / b);
14   }
15 }
16 
17 int main() {
18   //freopen("case.in", "r", stdin);
19   int n;
20   while (scanf("%d", &n) == 1) {
21     for (int i = 0, j = 1; i < n; i++, j += 2)  scanf("%d", v+ j);
22     bool f = true;
23     ll x, y, d, a, b, c;
24     for (a = 0; a < mod && f; a++) {
25       gcd(a + 1, mod, d, x, y);
26       c = v[3] - a * a * v[1];
27       if (c % d) continue;
28       b = (x * c / d + mod * 10) % mod;
29       f = false;
30       for (int i = 3; i <= 2 * n - 1 && !f; i += 2) {
31         v[i - 1] = (v[i - 2] * a + b) % mod;
32         if (v[i] != (v[i - 1] * a + b) % mod) f = true;
33       }
34       if (!f) v[2 * n] = (v[2 * n - 1] * a + b) % mod;
35     }
36     for (int i = 2; i <= 2 * n; i += 2) printf("%d\n", v[i]);
37   }
38   return 0;
39 }
代码君

 

例题10-3 uva10375

题意:略

题解:唯一分解定理。

 

技术分享
 1 /*zhen hao*/
 2 #include <bits/stdc++.h>
 3 using namespace std;
 4 
 5 const int maxn = 1e4 + 100;
 6 bool vis[maxn];
 7 vector<int> primes;
 8 int cnt[maxn];
 9 
10 void pre_slove(int n) {
11   int m = sqrt(n + 0.5);
12   for (int i = 2; i <= m; i++) if (!vis[i])
13     for (int j = i * i; j < maxn; j += i) vis[j] = true;
14 
15   for (int i = 2; i < maxn; i++)  if (!vis[i])
16     primes.push_back(i);
17 }
18 
19 void get_cnt(int n, int d) {
20   for (int i = 0; i < (int)primes.size() && primes[i] <= n; i++) {
21     while (n % primes[i] == 0) {
22       cnt[i] += d;
23       n /= primes[i];
24     }
25   }
26 }
27 
28 int main() {
29   //freopen("case.in","r", stdin);
30   pre_slove(maxn);
31   int p, q, r, s;
32   while (cin >> p >> q >> r >> s) {
33     memset(cnt, 0, sizeof cnt);
34     for (int i = 0; i < q; i++) {
35       get_cnt(p - i, 1);
36       get_cnt(i + 1, -1);
37     }
38     for (int i = 0; i < s; i++) {
39       get_cnt(r - i, -1);
40       get_cnt(i + 1, 1);
41     }
42     double ans = 1.0;
43     for (int i = 0; i < maxn; i++)  if (cnt[i]) {
44       ans *= powl(primes[i] * 1.0, cnt[i] * 1.0);
45     }
46     printf("%.5lf\n", ans);
47 
48   }
49   return 0;
50 }
代码君

 

例题10-4 uva 10791

题意:找几个数的公倍数为n的最小的和。

题解:唯一分解定理的各个项相加即是答案。

 

技术分享
 1 /*zhen hao*/
 2 #include <bits/stdc++.h>
 3 using namespace std;
 4 
 5 typedef long long ll;
 6 const int maxn = 1 << 16;
 7 bool vis[maxn];
 8 vector<int> primes;
 9 
10 void pre_slove(int n) {
11   int m = sqrt(n + 0.5);
12   for (int i = 2; i <= m; i++) if (!vis[i])
13     for (int j = i * i; j < n; j += i) vis[j] = true;
14 
15   for (int i = 2; i < n; i++) if (!vis[i])
16     primes.push_back(i);
17 }
18 
19 ll get_ans(ll n) {
20   if (n == 1) return 2;
21   ll ret = 0;
22   int cnt = 0;
23   for (int i = 0; i < (int)primes.size() && n >= primes[i]; i++)
24     if (n % primes[i] == 0) {
25       ll x = 1;
26       while (n % primes[i] == 0) {
27         x *= primes[i]; n /= primes[i];
28       }
29       cnt++; ret += x;
30     }
31   if (n > 1) { ret += n; cnt++; }
32   if (cnt == 1) ret++;
33   return ret;
34 }
35 
36 int main() {
37   //freopen("case.in", "r", stdin);
38   pre_slove(maxn);
39   ll n;
40   int tcase = 0;
41   while (cin >> n, n) {
42     cout << "Case " << ++tcase << ": " << get_ans(n) << endl;
43   }
44   return 0;
45 }
代码君

 

例题10-5 uva12716

题意:略

题解:具体思路跟紫书说的一样:先枚举约数c和其中一个较大的数a,然后得到b,然后判定是否存在gcd(a, a ^ c) = c;这样的复杂度是O(nlognlogn);

枚举a和c的代码如下:

for (int c = 1; c < maxn; c++)

for (int a = c + c; a < maxn; a += c)

就像素数筛法一样,对于c,2c,3c……都存在c这个约数。

最后发现有一个性质:满足a - c = b;所以就省去了一个log;

结合书和博客证明一下这个结论:

(1)首先前提是a - b <= a ^ b;

(2)设a - b = c;那么有a - b <= c;

(3)因为gcd(a, b) = c; 那么a = ca’, b = cb’,然后a - b = c(a’ - b’) >= c; 即c <= a - b <= c;

 

技术分享
 1 /*zhen hao*/
 2 #include <bits/stdc++.h>
 3 using namespace std;
 4 
 5 const int maxn = 3e7 + 1;
 6 int cnt[maxn], sum[maxn];
 7 
 8 void pre_slove() {
 9   for (int c = 1; c < maxn; c++)
10     for (int a = c + c; a < maxn; a += c) {
11       if (a - c == (a ^ c)) cnt[a]++;
12     }
13   for (int i = 1; i < maxn; i++)  sum[i] = sum[i - 1] + cnt[i];
14 }
15 
16 int main() {
17   //freopen("case.in", "r", stdin);
18   pre_slove();
19   int T, tcase = 0;
20   scanf("%d", &T);
21   while (T--) {
22     int n;
23     scanf("%d", &n);
24     printf("Case %d: %d\n", ++tcase, sum[n]);
25   }
26   return 0;
27 }
代码君

 

例题10-6 uva10820

题意:略

题解:书上很详细,就是找组合数C(0,n-1), C(1,n-1), ……,C(n-1,n-1)中有多少个能被m整除,方法是把m分解,找当前有没有全部覆盖它的所有因子即可。

 

技术分享
 1 /*zhen hao*/
 2 #include <bits/stdc++.h>
 3 #define fi first
 4 #define se second
 5 using namespace std;
 6 
 7 typedef pair<int,int> pii;
 8 const int maxn = 1e5 + 10;
 9 int mp1[maxn], mp2[maxn], cnt;
10 bool vis[maxn];
11 vector<int> primes, ans;
12 vector<pii> PII[maxn];
13 
14 void pre_slove() {
15   int m = sqrt(maxn + 0.5);
16   for (int i = 2; i <= m; i++)  if (!vis[i])
17     for (int j = i * i; j < maxn; j += i) vis[j] = 1;
18   for (int i = 2; i < maxn; i++) if (!vis[i])
19     primes.push_back(i);
20 
21   for (int i = 2; i < maxn; i++) {
22     int x = i;
23     for (int j = 0; j < (int)primes.size() && x >= primes[j]; j++) if (x % primes[j] == 0) {
24       int t = 0;
25       while (x % primes[j] == 0) {
26         x /= primes[j];
27         t++;
28       }
29       PII[i].push_back(make_pair(primes[j], t));
30     }
31   }
32 }
33 
34 void init() {
35   memset(mp1, 0, sizeof mp1);
36   memset(mp2, 0, sizeof mp2);
37   cnt = 0;
38   ans.clear();
39 }
40 
41 bool divide(int m, int n) {
42   if (m == 1) {
43     for (int i = 1; i <= n; i++)  ans.push_back(i);
44     return false;
45   }
46 
47   for (int i = 0; i < (int)primes.size() && m >= primes[i]; ++i) if (m % primes[i] == 0) {
48     ++cnt;
49     while (m % primes[i] == 0) {
50       m /= primes[i];
51       mp2[primes[i]]++;
52     }
53   }
54   if (m > 1) return false;
55   return true;
56 }
57 
58 void slove(int n) {
59   int now = 0, x;
60   for (int i = 1; i <= n; i++) {
61     x = n - i + 1;
62     for (int j = 0; j < (int)PII[x].size(); j++) {
63       pii& p = PII[x][j];
64       if (mp2[p.fi] && mp1[p.fi] < mp2[p.fi] && mp1[p.fi] + p.se >= mp2[p.fi]) now++;
65       mp1[p.fi] += p.se;
66     }
67     x = i;
68     for (int j = 0; j < (int)PII[x].size(); j++) {
69       pii& p = PII[x][j];
70       if (mp2[p.fi] && mp1[p.fi] >= mp2[p.fi] && mp1[p.fi] - p.se < mp2[p.fi]) now--;
71       mp1[p.fi] -= p.se;
72     }
73     if (now == cnt) ans.push_back(i + 1);
74   }
75 }
76 
77 int main() {
78   //freopen("case.in", "r", stdin);
79   pre_slove();
80   int n, m;
81   while (scanf("%d%d", &n, &m) == 2) {
82     init();
83 
84     if (divide(m, n))  slove(n - 1);
85 
86     printf("%d\n", (int)ans.size());
87     if (!ans.empty()) {
88       printf("%d", ans[0]);
89       for (int i = 1; i < (int)ans.size(); i++) printf(" %d", ans[i]);
90     }
91     printf("\n");
92   }
93   return 0;
94 }
代码君

 

例题10-7 uva10820

题意:计算1 <= x,y <= n有多少个满足gcd(x,y) = 1?

题解:略

 

技术分享
 1 /*zhen hao*/
 2 #include <bits/stdc++.h>
 3 using namespace std;
 4 
 5 typedef long long ll;
 6 const int maxn = 5e4 + 100;
 7 int phi[maxn];
 8 
 9 void phi_table(int n) {
10   for (int i = 2; i <= n; i++)  phi[i] = 0;
11   phi[1] = 1;
12   for (int i = 2; i <= n; i++) if (!phi[i])
13     for (int j = i; j <= n; j += i) {
14       if (!phi[j]) phi[j] = j;
15       phi[j] = phi[j] / i * (i - 1);
16     }
17   for (int i = 3; i <= n; i++) phi[i] += phi[i - 1];
18 }
19 
20 int main() {
21   //freopen("case.in", "r", stdin);
22   phi_table(maxn - 1);
23   int n;
24   while (scanf("%d", &n) && n) {
25     ll ans = phi[n] * 2 + 1;
26     if (n == 1) ans = 1;
27     printf("%d\n", ans);
28   }
29   return 0;
30 }
代码君

 

例题 10-8

题意:找这两个表中每一列都一样的字符,然后顺序取每一列,然后找字典序第k小。

题解:两种方法:

1、直接暴力dfs枚举

2、递推来找(像拆排列一样)

 

技术分享
 1 /*zhen hao*/
 2 #include <bits/stdc++.h>
 3 using namespace std;
 4 
 5 const int maxn = 90;
 6 int k, now;
 7 char s[maxn];
 8 char M1[maxn][maxn], M2[maxn][maxn];
 9 
10 bool dfs(int cur) {
11   if (cur == 5) {
12     if (++now == k) {
13       s[cur] = \0;
14       printf("%s\n", s);
15       return true;
16     }
17     return false;
18   }
19 
20   bool vis1[30], vis2[30];
21   memset(vis1, false, sizeof vis1);
22   memset(vis2, false, sizeof vis2);
23 
24   for (int i = 0; i < 6; i++) vis1[M1[i][cur] - A] = true;
25   for (int i = 0; i < 6; i++) vis2[M2[i][cur] - A] = true;
26 
27   for (int i = 0; i < 26; i++) if (vis1[i] && vis2[i]) {
28     s[cur] = A + i;
29     if (dfs(cur + 1)) return true;
30   }
31   return false;
32 }
33 
34 int main() {
35   //freopen("case.in", "r", stdin);
36   int T;
37   scanf("%d", &T);
38   while (T--) {
39     scanf("%d", &k);
40     for (int i = 0; i < 6; i++) scanf("%s", M1[i]);
41     for (int i = 0; i < 6; i++) scanf("%s", M2[i]);
42 
43     now = 0;
44     if (!dfs(0))  printf("NO\n");
45   }
46   return 0;
47 }
代码君(dfs)

 

技术分享
 1 /*zhen hao*/
 2 #include <bits/stdc++.h>
 3 using namespace std;
 4 
 5 const int maxn = 10;
 6 char M1[maxn][maxn], M2[maxn][maxn], s[maxn];
 7 vector<char> V[maxn];
 8 bool vis1[26], vis2[26];
 9 
10 int main() {
11   //freopen("case.in", "r", stdin);
12   int T, k;
13   scanf("%d", &T);
14   while (T--) {
15     scanf("%d", &k);
16     for (int i = 0; i < 6; i++) scanf("%s", M1[i]);
17     for (int i = 0; i < 6; i++) scanf("%s", M2[i]);
18 
19     int tot = 1;
20     for (int j = 0; j < 5; j++) {
21       V[j].clear();
22       memset(vis1, false, sizeof vis1);
23       memset(vis2, false, sizeof vis2);
24 
25       for (int i = 0; i < 6; i++) vis1[M1[i][j] - A] = true;
26       for (int i = 0; i < 6; i++) vis2[M2[i][j] - A] = true;
27       for (int i = 0; i < 26; i++)  if (vis1[i] && vis2[i])
28         V[j].push_back(i + A);
29         
30       tot *= int(V[j].size());
31     }
32 
33     if (k > tot) {
34       puts("NO"); continue;
35     }
36 
37     for (int j = 0; j < 5; j++) {
38       int i = 0, x = tot / V[j].size(), now = x;
39       while (now < k) now += x, i++;
40       k -= i * x;
41       tot = x;
42       s[j] = V[j][i];
43     }
44     s[5] = \0;
45     printf("%s\n", s);
46   }
47   return 0;
48 }
代码君(递推)

 

例题 10-9 uva 1636

题意:略

题解:略

 

技术分享
 1 /*zhen hao*/
 2 #include <bits/stdc++.h>
 3 using namespace std;
 4 
 5 int slove(string s) {
 6   int n = s.length(), t1 = 0, t2 = 0;
 7   for (int i = 0; i < n; i++)
 8     if (s[i] == 0) {
 9       t1++;
10       if (s[(i + 1) % n] == 0) t2++;
11     }
12   return t2 * n - t1 * t1;
13 }
14 
15 int main() {
16   //freopen("case.in", "r", stdin);
17   string s;
18   while (cin >> s) {
19     int ans = slove(s);
20     if (!ans) puts("EQUAL");
21     else if (ans > 0) puts("SHOOT");
22     else puts("ROTATE");
23   }
24   return 0;
25 }
代码君

 

例题10-10 uva 10491

题意:略

题解:略

 

技术分享
 1 /*zhen hao*/
 2 #include <bits/stdc++.h>
 3 using namespace std;
 4 
 5 int main() {
 6   //freopen("case.in", "r", stdin);
 7   int a, b, c;
 8   while (cin >> a >> b >> c) {
 9     printf("%.5lf\n", double(a * b + b * (b - 1)) / (a + b) / (a + b - c - 1));
10   }
11   return 0;
12 }
代码君

 

例题 10-11 uva 11181

题意:略

题解:按照书上的描述进行枚举

 

技术分享
 1 /*zhen hao*/
 2 #include <bits/stdc++.h>
 3 using namespace std;
 4 
 5 const int maxn = 21;
 6 int n, r, v[maxn];
 7 double p[maxn], pos[maxn], tot;
 8 
 9 void dfs(int cur, int sum) {
10   if (sum + n - cur < r) return;
11   if (sum > r) return;
12   if (cur == n) {
13     if (sum == r) {
14       double temp = 1.0;
15       for (int i = 0; i < n; i++)
16         temp *= (v[i] ? p[i] : 1 - p[i]);
17       tot += temp;
18       for (int i = 0; i < n; i++)
19         if (v[i]) pos[i] += temp;
20     }
21     return;
22   }
23   v[cur] = 0;
24   dfs(cur + 1, sum);
25   v[cur] = 1;
26   dfs(cur + 1, sum + 1);
27 }
28 
29 int main() {
30   //freopen("case.in", "r", stdin);
31   int tcase = 0;
32   while (scanf("%d%d", &n, &r) == 2 && n | r) {
33     for (int i = 0; i < n; i++) scanf("%lf", p + i);
34     tot = 0;
35     memset(pos, 0, sizeof pos);
36     dfs(0, 0);
37     printf("Case %d:\n", ++tcase);
38     for (int i = 0; i < n; i++) printf("%.6lf\n", pos[i] / tot);
39   }
40   return 0;
41 }
代码君

 

例题10-12 uva1637

题意:略

题解:略

 

技术分享
 1 /*zhen hao*/
 2 #include <bits/stdc++.h>
 3 using namespace std;
 4 
 5 const int maxs = 1953125;
 6 char s[10][5][3];
 7 int vis[maxs], sta[10], base[10], tcase;
 8 double dp[maxs];
 9 
10 int decode() {
11   int ret = 0;
12   for (int i = 8; i >= 0; i--) ret = ret * 5 + sta[i];
13   return ret;
14 }
15 
16 double d() {
17   int x = decode();
18   if (x == 0) return 1.0;
19   if (vis[x] == tcase) return dp[x];
20   vis[x] = tcase;
21   double& ans = dp[x]; ans = 0;
22   int cnt = 0;
23   for (int i = 0; i < 9; i++)
24     for (int j = i + 1; j < 9; j++)
25       if (sta[i] && sta[j] && s[i][sta[i]][0] == s[j][sta[j]][0]) {
26         sta[i]--; sta[j]--;
27         ans += d();
28         cnt++;
29         sta[i]++; sta[j]++;
30       }
31   if (cnt) ans /= cnt;
32   return ans;
33 }
34 
35 int main() {
36   //freopen("case.in", "r", stdin);
37   tcase = 0;
38   while (~scanf("%s", s[0][1])) {
39     ++tcase;
40     for (int i = 0; i < 9; i++)
41       for (int j = 1; j <= 4; j++) {
42         if (i == 0 && j == 1) continue;
43         scanf("%s", s[i][j]);
44       }
45     for (int i = 0; i < 9; i++) sta[i] = 4;
46     printf("%.6lf\n", d());
47   }
48   return 0;
49 }
代码君

 

例题10-13 uva580

题意:略

题解:这里我觉得书上的方法太麻烦了,所以用了dp[i][j]表示以i为结尾j个危险物的方案数,然后总方案减去即可,很简单的递推题。

 

技术分享
 1 /*zhen hao*/
 2 #include <bits/stdc++.h>
 3 using namespace std;
 4 
 5 typedef long long ll;
 6 const int maxn = 40;
 7 ll dp[maxn][3];
 8 
 9 void init() {
10   dp[2][0] = 2;
11   dp[2][1] = dp[2][2] = dp[1][0] = dp[1][1] = 1;
12   for (int i = 3; i < maxn; i++) {
13     for (int j = 0; j <= 2; j++) dp[i][0] += dp[i - 1][j];
14     dp[i][1] = dp[i - 1][0];
15     dp[i][2] = dp[i - 1][1];
16   }
17 }
18 
19 int main() {
20 //  freopen("case.in", "r", stdin);
21   init();
22   int n;
23   while (cin >> n, n) {
24     ll ans = 0;
25     for (int i = 0; i <= 2; i++)  ans += dp[n][i];
26     cout << (1LL << n) - ans << endl;
27   }
28 }
代码君

 

例题10-14 uva 12034

题意:略

题解:略

 

技术分享
 1 /*zhen hao*/
 2 #include <bits/stdc++.h>
 3 using namespace std;
 4 
 5 typedef long long ll;
 6 const int maxn = 1100, mod = 10056;
 7 int f[maxn], c[maxn][maxn];
 8 
 9 void init() {
10   for (int i = 0; i < maxn; i++) {
11     c[i][0] = 1;
12     for (int j = 1; j <= i; j++)  c[i][j] = (c[i - 1][j - 1] + c[i - 1][j]) % mod;
13   }
14 
15   f[0] = f[1] = 1;
16   for (int i = 2; i < maxn; i++)
17     for (int j = 1; j <= i; j++)
18       f[i] = (f[i] + f[i - j] * c[i][j] % mod) % mod;
19 }
20 
21 int main() {
22 //  freopen("case.in", "r", stdin);
23   int T, tcase = 0;
24   cin >> T;
25   init();
26   while (T--) {
27     int n;
28     scanf("%d", &n);
29     printf("Case %d: %d\n", ++tcase, f[n]);
30   }
31   return 0;
32 }
代码君

 

例题 10-15 uva 1638

题意:略

题解:略

 

技术分享
 1 /*zhen hao*/
 2 #include <bits/stdc++.h>
 3 using namespace std;
 4 
 5 typedef long long ll;
 6 const int maxn = 21;
 7 ll dp[maxn][maxn][maxn];
 8 
 9 void init() {
10   dp[1][1][1] = 1;
11   for (int i = 2; i < maxn; i++)
12     for (int l = 1; l <= i; l++)
13       for (int r = 1; r <= i; r++)
14         dp[i][l][r] = dp[i - 1][l - 1][r] + dp[i - 1][l][r - 1] + dp[i - 1][l][r] * (i - 2);
15 }
16 
17 int main() {
18 //  freopen("case.in", "r", stdin);
19   init();
20   int T;
21   cin >> T;
22   while (T--) {
23     int n, l, r;
24     cin >> n >> l >> r;
25     cout << dp[n][l][r] << endl;
26   }
27   return 0;
28 }
代码君

 

例题 10-16 uva 12230

题意:简单的概率题

 

技术分享
 1 /*zhen hao*/
 2 #include <bits/stdc++.h>
 3 using namespace std;
 4 
 5 #define lson l, m, rt*2
 6 #define rson m + 1, r, rt*2+1
 7 #define xx first
 8 #define yy second
 9 
10 typedef pair<int,int> pii;
11 typedef long long ll;
12 typedef unsigned long long ull;
13 
14 int main() {
15 //  freopen("case.in", "r", stdin);
16   int n, D, tcase = 0;
17   while (scanf("%d%d", &n, &D) == 2 && n + D) {
18     double res = 0;
19     int tot = 0;
20     for (int i = 0; i < n; i++) {
21       int p, l, v;
22       scanf("%d%d%d", &p, &l, &v);
23       res += 2.0 * l / v;
24       tot += l;
25     }
26     res += D - tot;
27     printf("Case %d: %.3lf\n\n", ++tcase, res);
28   }
29   return 0;
30 }
代码君

 

例题10-17 uva 1639

题意:略

题解:这里组合数是要用log优化,C(n,m) = F(n) / F(m) / F(n - m),然后就是两边求一个ln,得ln(C(n,m)) = ln(F(n)) - ln(F(m)) - ln(F(n - m)),然后double精度不够,要用long double来处理这个log。还有一点要注意的是当p = 0或者p = 1的时候直接输出n。

 

技术分享
/*zhen hao*/
#include <bits/stdc++.h>
using namespace std;

#define lson l, m, rt*2
#define rson m + 1, r, rt*2+1
#define xx first
#define yy second

typedef pair<int,int> pii;
typedef long long ll;
typedef unsigned long long ull;

const int maxn = 4e5 + 100;
long double F[maxn];

void init() {
  F[0] = 0;
  for (int i = 1; i < maxn; i++) {
    F[i] = F[i - 1] + log(1.0 * i);
  }
//  cout << exp(F[5] - F[3] - F[2]) << endl;
}

double get_res(int n, int i, double p, double q) {
  return F[2 * n - i] - F[n - i] - F[n] + double(n + 1) * log(p) + double(n - i) * log(q);
}

int main() {
//  freopen("case.in", "r", stdin);
  init();
  int n, tcase = 0;
  double p;
  while (scanf("%d%lf", &n, &p) == 2) {
    double res = 0;
    for (int i = 1; i <= n; i++) {
      res += (exp(get_res(n, i, p, 1 - p)) + exp(get_res(n, i, 1 - p, p))) * i;
    }
    if (p == 1 || p == 0) res = n;
    printf("Case %d: %.6lf\n", ++tcase, res);
  }
  return 0;
}
代码君

 

例题10-18 uva10288

题意:略

题解:这里复述一下那个化简公式的过程,实际上白书的期望题也有说到:

当t = 1, p = (1 - s);

当t = 2, p = (1 - s) * s;

当t = 3, p = (1 - s) * s2

然后设期望为E,则

E = (1 - s) * (1 + s + s2 + …… + sn) (1)

sE = (1 - s) * (s + s2 + s3 + …… + sn) (2)

(1) - (2) 得

E = 1 + s + s2 + …… + sn = 1 / (1 - s);

 

技术分享
 1 /*zhen hao*/
 2 #include <bits/stdc++.h>
 3 using namespace std;
 4 
 5 #define lson l, m, rt*2
 6 #define rson m + 1, r, rt*2+1
 7 #define xx first
 8 #define yy second
 9 
10 typedef pair<int,int> pii;
11 typedef long long ll;
12 typedef unsigned long long ull;
13 
14 ll gcd(ll a, ll b) {
15   if (!b) return a;
16   else return gcd(b, a % b);
17 }
18 
19 int cal(ll x) {
20   int ret = 0;
21   while (x) {
22     ret++;
23     x /= 10;
24   }
25   return ret;
26 }
27 
28 int main() {
29 //  freopen("case.in", "r", stdin);
30   int n;
31   while (~scanf("%d", &n)) {
32     ll res1, res2;
33     res1 = res2 = 0;
34     for (int k = 0; k < n; k++) {
35       ll a = n, b = n - k;
36       if (res1 == 0) {
37         res1 = a; res2 = b;
38       } else {
39         ll ta = res1, tb = res2, d;
40         res1 = a * tb + b * ta;
41         res2 = b * tb;
42         d = gcd(res1, res2);
43         res1 /= d;
44         res2 /= d;
45       }
46     }
47     if (res1 % res2 == 0) {
48       cout << res1 / res2 << endl;
49     } else {
50       ll x = res1 / res2, y = res1 - res2 * x, z = res2;
51       int c1 = cal(x), c2 = cal(z);
52       for (int i = 0; i <= c1; i++) putchar( );
53       cout << y << \n << x <<  ;
54       for (int i = 0; i < c2; i++) putchar(-);
55       puts("");
56       for (int i = 0; i <= c1; i++) putchar( );
57       cout << z << endl;
58     }
59   }
60   return 0;
61 }
代码君

 

例题 10-19 uva 10346

题意:略

题解:直接按照书上给的公式来码,然后注意如果这个s接近于的话,那就输出1,如果这个a * b < s,就直接输出0;

 

技术分享
 1 /*zhen hao*/
 2 #include <bits/stdc++.h>
 3 using namespace std;
 4 
 5 #define ld long double
 6 
 7 const double eps = 1e-6;
 8 
 9 int main() {
10 //  freopen("case.in", "r", stdin);
11   int T;
12   cin >> T;
13   while (T--) {
14     double a, b, s, res;
15     scanf("%lf%lf%lf", &a, &b, &s);
16     if (a * b < s) res = 0;
17     else if (abs(s) < eps) res = 1.0;
18     else res = (a * b - s - s * log(a * b / s)) / (a * b);
19     printf("%.6f%%\n", res * 100);
20   }
21   return 0;
22 }
代码君

 

例题10-20 uva 10900

题意:略

题解:这题可以算是难题了,但是书上的分析也很透彻,也就是递推算出最有策略下的奖金期望,当i = n时,那么肯定直接答对的话就是拿2 ^ n,然后对于上一道题,分两种情况,给出一个临界概率p0,也就是t~p0就直接放弃,p0~1就直接答题,然后只有答对才有奖金,那么就还要再乘多一个平均能够答对的概率,也就是(p0 + 1) / 2;最终递推到第0题就是答案,代码很简单,但是思路很复杂,这也许是大部分数学题目的特点。

 

技术分享
 1 /*zhen hao*/
 2 #include <bits/stdc++.h>
 3 using namespace std;
 4 
 5 const int maxn = 40;
 6 int n;
 7 double t;
 8 
 9 double d(int x) {
10   if (x == n) return double(1 << x);
11   double temp = d(x + 1);
12   double p0 = max(t, (1 << x) / temp);
13   double p = (p0 - t) / (1 - t), q = 1 - p;
14   return p * (1 << x) + q * temp * (1 + p0) / 2;
15 }
16 
17 int main() {
18 //  freopen("case.in", "r", stdin);
19   while (cin >> n >> t, n) {
20     printf("%.3f\n", d(0));
21   }
22   return 0;
23 }
代码君

 

例题10-21 uva 11971

题意:略

题解:略

 

技术分享
 1 /*zhen hao*/
 2 #include <bits/stdc++.h>
 3 using namespace std;
 4 
 5 typedef long long ll;
 6 
 7 ll gcd(ll a, ll b) {
 8   if (!b) return a;
 9   else return gcd(b, a % b);
10 }
11 
12 int main() {
13 //  freopen("case.in", "r", stdin);
14   int T, tcase = 0;
15   cin >> T;
16   while (T--) {
17     ll n, k, a, b, d;
18     cin >> n >> k;
19     a = ((1LL << k) - k - 1);
20     b = 1LL << k;
21     if (a == 0) b = 1;
22     else {
23       d = gcd(a, b);
24       a /= d;
25       b /= d;
26     }
27     printf("Case #%d: %lld/%lld\n", ++tcase, a, b);
28   }
29   return 0;
30 }
代码君

 

 

 

第10章例题(紫书)

标签:

原文地址:http://www.cnblogs.com/zhenhao1/p/5548038.html

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