• 第10章例题(紫书)


    21/29

    题目都很基础,有很多题书上讲得比较详细,然后隔得时间有点久,所以具体什么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
    ", 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
    ", 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
    ", 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
    ", ++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
    ", (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("
    ");
    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
    ", 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] = '';
    14       printf("%s
    ", 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
    ");
    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] = '';
    45     printf("%s
    ", 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
    ", 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:
    ", ++tcase);
    38     for (int i = 0; i < n; i++) printf("%.6lf
    ", 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
    ", 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
    ", ++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
    
    ", ++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
    ", ++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 << '
    ' << 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%%
    ", 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
    ", 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
    ", ++tcase, a, b);
    28   }
    29   return 0;
    30 }
    代码君

     

  • 相关阅读:
    个人网站第一期完成
    nodebb在阿里云主机部署过程
    mongoengine教程1
    quick cocos 的scheduler 定时器
    cocos2dx调度器scheduler
    Cocos2d-x中Vector使用
    Google分布式系统三驾马车: GFS,mapreduce,Bigtable
    Linux使用记
    Eclipse快捷键总结
    详解iOS App生命周期(转)
  • 原文地址:https://www.cnblogs.com/zhenhao1/p/5548038.html
Copyright © 2020-2023  润新知