标签:
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 }
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 }
标签:
原文地址:http://www.cnblogs.com/zhenhao1/p/5548038.html