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

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

至少K张

转化为

总数 - 至多K张

(为什么要这样自己想)

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

那么可以总结出

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

 f[i][] = f[i - ][] + f[i - ][];
if(i == k) f[i][] -= ;
else if(i > k) f[i][] -= f[i - k][];

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

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

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

 #include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <vector>
#include <cassert>
using namespace std; const int maxn = ; struct BigInteger {
typedef unsigned long long LL; static const int BASE = ;
static const int WIDTH = ;
vector<int> s; BigInteger& clean(){while(!s.back()&&s.size()>)s.pop_back(); return *this;}
BigInteger(LL num = ) {*this = num;}
BigInteger(string s) {*this = s;}
BigInteger& operator = (long long num) {
s.clear();
do {
s.push_back(num % BASE);
num /= BASE;
} while (num > );
return *this;
}
BigInteger& operator = (const string& str) {
s.clear();
int x, len = (str.length() - ) / WIDTH + ;
for (int i = ; i < len; i++) {
int end = str.length() - i*WIDTH;
int start = max(, end - WIDTH);
sscanf(str.substr(start,end-start).c_str(), "%d", &x);
s.push_back(x);
}
return (*this).clean();
} BigInteger operator + (const BigInteger& b) const {
BigInteger c; c.s.clear();
for (int i = , g = ; ; i++) {
if (g == && i >= s.size() && i >= b.s.size()) break;
int x = g;
if (i < s.size()) x += s[i];
if (i < b.s.size()) x += b.s[i];
c.s.push_back(x % BASE);
g = x / BASE;
}
return c;
}
BigInteger operator - (const BigInteger& b) const {
assert(b <= *this); // 减数不能大于被减数
BigInteger c; c.s.clear();
for (int i = , g = ; ; i++) {
if (g == && i >= s.size() && i >= b.s.size()) break;
int x = s[i] + g;
if (i < b.s.size()) x -= b.s[i];
if (x < ) {g = -; x += BASE;} else g = ;
c.s.push_back(x);
}
return c.clean();
}
BigInteger operator * (const BigInteger& b) const {
int i, j; LL g;
vector<LL> v(s.size()+b.s.size(), );
BigInteger c; c.s.clear();
for(i=;i<s.size();i++) for(j=;j<b.s.size();j++) v[i+j]+=LL(s[i])*b.s[j];
for (i = , g = ; ; i++) {
if (g == && i >= v.size()) break;
LL x = v[i] + g;
c.s.push_back(x % BASE);
g = x / BASE;
}
return c.clean();
}
BigInteger operator / (const BigInteger& b) const {
assert(b > ); // 除数必须大于0
BigInteger c = *this; // 商:主要是让c.s和(*this).s的vector一样大
BigInteger m; // 余数:初始化为0
for (int i = s.size()-; i >= ; i--) {
m = m*BASE + s[i];
c.s[i] = bsearch(b, m);
m -= b*c.s[i];
}
return c.clean();
}
BigInteger operator % (const BigInteger& b) const { //方法与除法相同
BigInteger c = *this;
BigInteger m;
for (int i = s.size()-; i >= ; i--) {
m = m*BASE + s[i];
c.s[i] = bsearch(b, m);
m -= b*c.s[i];
}
return m;
}
// 二分法找出满足bx<=m的最大的x
int bsearch(const BigInteger& b, const BigInteger& m) const{
int L = , R = BASE-, x;
while () {
x = (L+R)>>;
if (b*x<=m) {if (b*(x+)>m) return x; else L = x;}
else R = x;
}
}
BigInteger& operator += (const BigInteger& b) {*this = *this + b; return *this;}
BigInteger& operator -= (const BigInteger& b) {*this = *this - b; return *this;}
BigInteger& operator *= (const BigInteger& b) {*this = *this * b; return *this;}
BigInteger& operator /= (const BigInteger& b) {*this = *this / b; return *this;}
BigInteger& operator %= (const BigInteger& b) {*this = *this % b; return *this;} bool operator < (const BigInteger& b) const {
if (s.size() != b.s.size()) return s.size() < b.s.size();
for (int i = s.size()-; i >= ; i--)
if (s[i] != b.s[i]) return s[i] < b.s[i];
return false;
}
bool operator >(const BigInteger& b) const{return b < *this;}
bool operator<=(const BigInteger& b) const{return !(b < *this);}
bool operator>=(const BigInteger& b) const{return !(*this < b);}
bool operator!=(const BigInteger& b) const{return b < *this || *this < b;}
bool operator==(const BigInteger& b) const{return !(b < *this) && !(b > *this);}
}; ostream& operator << (ostream& out, const BigInteger& x) {
out << x.s.back();
for (int i = x.s.size()-; i >= ; i--) {
char buf[];
sprintf(buf, "%08d", x.s[i]);
for (int j = ; j < strlen(buf); j++) out << buf[j];
}
return out;
} istream& operator >> (istream& in, BigInteger& x) {
string s;
if (!(in >> s)) return in;
x = s;
return in;
} int n, k;
BigInteger f[maxn][]; int main() {
while(cin >> n >> k) {
memset(f, , sizeof(f));
f[][] = ;
for(int i = ; i <= n; i++) {
f[i][] = f[i - ][] + f[i - ][];
f[i][] = f[i - ][] + f[i - ][];
if(i == k) f[i][] = f[i][] - ;
else if(i > k) f[i][] = f[i][] - f[i - k][];
}
BigInteger a = , t = ;
for(int i = ; i < n; i++) a = t * a;
cout << a - f[n][] - f[n][] << endl;
}
}

最新文章

  1. [SL] Silverlight + WCF Demo项目
  2. 标题栏Menu
  3. GPIO口及中断API函数【转】
  4. [Node.js] Promise,Q及Async
  5. grep -n 显示行号
  6. android 6.0权限处理
  7. 嵌入式 hi3518平台指定网卡测试是否通外网
  8. 基础面试题——Javascript
  9. Socket知识总结
  10. flowplayer+flashhls使用过程中发现的一些小问题
  11. 虚拟机最佳实践:单个 VM、临时存储和已上传磁盘
  12. 习题3.15 自调整表Find例程
  13. JavaWeb解释一下什么是 servlet?
  14. Unity 3D 建立开发环境
  15. 数据库的事务、ACID及隔离级别
  16. Python中高阶函数讲解
  17. ios屏幕怎么投屏到电脑显示器
  18. java实现excel生成和导出
  19. IT行业创新的读后感
  20. 控制 datetimepicker 显示位置

热门文章

  1. canvas处理图片
  2. js的运算小数点的问题
  3. Django-------&gt;&gt;&gt;modle
  4. BZOJ 1594 [Usaco2008 Jan]猜数游戏(线段数)
  5. 【jQuery01】添加添加div
  6. java几种远程服务调用协议的比较
  7. ubuntu 16.04 安装KVM-多系统
  8. echars 在vue v-if 切换会 显示不出来或者显示出来但是不是百分百显示
  9. P1064 金明的预算方案 (依赖性背包问题)
  10. 2015 Multi-University Training Contest 4 hdu 5336 XYZ and Drops