题解 UVA10328 【Coin Toss】

这道题目其实就是说有N张纸牌,问至少连续K张正面朝上的可能性是多少。


可以用递推做。
首先我们将题目所求从


至少K张


转化为


总数 - 至多K张


(为什么要这样自己想)

设F[i][j]为前i个纸牌至多K张的种数。其中j记录第i张纸牌的状态,1为正面朝上,0为反面。

那么可以总结出

 1 f[i][0] = f[i - 1][0] + f[i - 1][1];  

1 f[i][1] = f[i - 1][0] + f[i - 1][1];
2 if(i == k) f[i][1] -= 1;
3 else if(i > k) f[i][1] -= f[i - k][0];

最后要记住这道题需要写高精,我第一次就是这么扑街的。

注:高精用的模板,手残就全加上了,事实上只用加减法。

AC代码如下(洛谷上不知道为什么被积极拒绝,只好去Vjudge上提交。。。没去UVa才不是因为我没有注册。)

  1 #include <iostream> 
  2 #include <cstdio>
  3 #include <algorithm>
  4 #include <cstring>
  5 #include <cmath> 
  6 #include <vector>
  7 #include <cassert>
  8 using namespace std;
  9 
 10 const int maxn = 105;
 11 
 12 struct BigInteger {
 13     typedef unsigned long long LL;
 14 
 15     static const int BASE = 100000000;
 16     static const int WIDTH = 8;
 17     vector<int> s;
 18 
 19     BigInteger& clean(){while(!s.back()&&s.size()>1)s.pop_back(); return *this;}
 20     BigInteger(LL num = 0) {*this = num;}
 21     BigInteger(string s) {*this = s;}
 22     BigInteger& operator = (long long num) {
 23         s.clear();
 24         do {
 25             s.push_back(num % BASE);
 26             num /= BASE;
 27         } while (num > 0);
 28         return *this;
 29     }
 30     BigInteger& operator = (const string& str) {
 31         s.clear();
 32         int x, len = (str.length() - 1) / WIDTH + 1;
 33         for (int i = 0; i < len; i++) {
 34             int end = str.length() - i*WIDTH;
 35             int start = max(0, end - WIDTH);
 36             sscanf(str.substr(start,end-start).c_str(), "%d", &x);
 37             s.push_back(x);
 38         }
 39         return (*this).clean();
 40     }
 41 
 42     BigInteger operator + (const BigInteger& b) const {
 43         BigInteger c; c.s.clear();
 44         for (int i = 0, g = 0; ; i++) {
 45             if (g == 0 && i >= s.size() && i >= b.s.size()) break;
 46             int x = g;
 47             if (i < s.size()) x += s[i];
 48             if (i < b.s.size()) x += b.s[i];
 49             c.s.push_back(x % BASE);
 50             g = x / BASE;
 51         }
 52         return c;
 53     }
 54     BigInteger operator - (const BigInteger& b) const {
 55         assert(b <= *this); // 减数不能大于被减数
 56         BigInteger c; c.s.clear();
 57         for (int i = 0, g = 0; ; i++) {
 58             if (g == 0 && i >= s.size() && i >= b.s.size()) break;
 59             int x = s[i] + g;
 60             if (i < b.s.size()) x -= b.s[i];
 61             if (x < 0) {g = -1; x += BASE;} else g = 0;
 62             c.s.push_back(x);
 63         }
 64         return c.clean();
 65     }
 66     BigInteger operator * (const BigInteger& b) const {
 67         int i, j; LL g;
 68         vector<LL> v(s.size()+b.s.size(), 0);
 69         BigInteger c; c.s.clear();
 70         for(i=0;i<s.size();i++) for(j=0;j<b.s.size();j++) v[i+j]+=LL(s[i])*b.s[j];
 71         for (i = 0, g = 0; ; i++) {
 72             if (g ==0 && i >= v.size()) break;
 73             LL x = v[i] + g;
 74             c.s.push_back(x % BASE);
 75             g = x / BASE;
 76         }
 77         return c.clean();
 78     }
 79     BigInteger operator / (const BigInteger& b) const {
 80         assert(b > 0);  // 除数必须大于0
 81         BigInteger c = *this;       // 商:主要是让c.s和(*this).s的vector一样大
 82         BigInteger m;               // 余数:初始化为0
 83         for (int i = s.size()-1; i >= 0; i--) {
 84             m = m*BASE + s[i];
 85             c.s[i] = bsearch(b, m);
 86             m -= b*c.s[i];
 87         }
 88         return c.clean();
 89     }
 90     BigInteger operator % (const BigInteger& b) const { //方法与除法相同
 91         BigInteger c = *this;
 92         BigInteger m;
 93         for (int i = s.size()-1; i >= 0; i--) {
 94             m = m*BASE + s[i];
 95             c.s[i] = bsearch(b, m);
 96             m -= b*c.s[i];
 97         }
 98         return m;
 99     }
100     // 二分法找出满足bx<=m的最大的x
101     int bsearch(const BigInteger& b, const BigInteger& m) const{
102         int L = 0, R = BASE-1, x;
103         while (1) {
104             x = (L+R)>>1;
105             if (b*x<=m) {if (b*(x+1)>m) return x; else L = x;}
106             else R = x;
107         }
108     }
109     BigInteger& operator += (const BigInteger& b) {*this = *this + b; return *this;}
110     BigInteger& operator -= (const BigInteger& b) {*this = *this - b; return *this;}
111     BigInteger& operator *= (const BigInteger& b) {*this = *this * b; return *this;}
112     BigInteger& operator /= (const BigInteger& b) {*this = *this / b; return *this;}
113     BigInteger& operator %= (const BigInteger& b) {*this = *this % b; return *this;}
114 
115     bool operator < (const BigInteger& b) const {
116         if (s.size() != b.s.size()) return s.size() < b.s.size();
117         for (int i = s.size()-1; i >= 0; i--)
118             if (s[i] != b.s[i]) return s[i] < b.s[i];
119         return false;
120     }
121     bool operator >(const BigInteger& b) const{return b < *this;}
122     bool operator<=(const BigInteger& b) const{return !(b < *this);}
123     bool operator>=(const BigInteger& b) const{return !(*this < b);}
124     bool operator!=(const BigInteger& b) const{return b < *this || *this < b;}
125     bool operator==(const BigInteger& b) const{return !(b < *this) && !(b > *this);}
126 };
127 
128 ostream& operator << (ostream& out, const BigInteger& x) {
129     out << x.s.back();
130     for (int i = x.s.size()-2; i >= 0; i--) {
131         char buf[20];
132         sprintf(buf, "%08d", x.s[i]);
133         for (int j = 0; j < strlen(buf); j++) out << buf[j];
134     }
135     return out;
136 }
137 
138 istream& operator >> (istream& in, BigInteger& x) {
139     string s;
140     if (!(in >> s)) return in;
141     x = s;
142     return in;
143 }
144 
145 int n, k;
146 BigInteger f[maxn][2];
147 
148 int main() {
149     while(cin >> n >> k) {
150         memset(f, 0, sizeof(f));
151         f[0][1] = 1;
152         for(int i = 1; i <= n; i++) {
153             f[i][0] = f[i - 1][0] + f[i - 1][1]; 
154             f[i][1] = f[i - 1][0] + f[i - 1][1];
155             if(i == k) f[i][1] = f[i][1] - 1;
156             else if(i > k) f[i][1] = f[i][1] - f[i - k][0];
157         }
158         BigInteger a = 1, t = 2;
159         for(int i = 0; i < n; i++) a = t * a;
160         cout << a - f[n][1] - f[n][0] << endl;
161     }
162 }
原文地址:https://www.cnblogs.com/ilverene/p/UVA10328.html