UVaOJ 10328 Coin Toss
https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=1269
题意:一共n张牌,求至少连续k张牌是正面的排列情况有多少种(1<=k<=n<=100)
思路:将至少转换为至多,所有排列情况减去至多连续k-1张牌是正面的排列情况,就可以得到至少k张连续正面的情况了
所有排列情况好求,就是2^n,要注意到n最多为100,超过了long long的范围,可以用两个long long需要模拟一下。
至多有x张牌是正面的情况,用s[0][i]表示第i张是反面的时候,至多x张牌连续正面的情况有多少个
用s[1][i]表示第i张是正面的时候,至多x张牌连续正面的情况有多少个
对于反面 s[0][i]=s[0][i-1]+s[1][i-1] 反面与限制条件无关,直接就等于之前的所有情况之和;
对于正面 如果i<=x s[1][i]=s[1][i-1]+s[0][i-1] 这时肯定不会出现连续的正面超过i的情况,所有也可以直接等于之前的所有情况之和;
如果i>x s[1][i]=s[1][i-1]+s[0][i-1]-s[0][i-k-1] i>x的时候,第i张如果要放正面,就需要排除之前从i-1到i-k连续k张是正面的那些排列,所有需要排除的情况都在s[0][i-k-1],因为从i-1到i-k的k张连续正面一定是从一个反面(i-k的前一个i-k-1一定是反面)开始的
1 #include<iostream> 2 #include<string.h> 3 #include<stdio.h> 4 #define ll long long 5 #define Flag 1000000000000000//大于等于的时候进位 6 using namespace std; 7 struct Num//用两个longlong模拟,重载了加减方便计算 8 { 9 ll H,L; 10 Num() 11 { 12 H=L=0; 13 } 14 void quan(int n)//求2^n,n张牌所有的排列情况 15 { 16 this->H=0; 17 this->L=1; 18 while(n--) 19 { 20 this->L<<=1; 21 this->H<<=1; 22 if(this->L>Flag)this->L-=Flag,this->H++; 23 } 24 } 25 Num operator +(const Num& b)const 26 { 27 Num tem; 28 tem.L = this->L + b.L; 29 tem.H = this->H + b.H; 30 if(tem.L>=Flag) 31 { 32 tem.H++; 33 tem.L-=Flag; 34 } 35 return tem; 36 } 37 Num operator -(const Num& b)const 38 { 39 Num tem; 40 if(this->L<b.L) 41 { 42 tem.L = this->L + Flag -b.L; 43 tem.H = this->H - b.H - 1; 44 } 45 else 46 { 47 tem.L = this->L - b.L; 48 tem.H = this->H - b.H; 49 } 50 return tem; 51 } 52 void display()//输出 53 { 54 if(this->H) 55 { 56 printf("%lld%015lld\n",this->H,this->L); 57 } 58 else 59 { 60 printf("%lld\n",this->L); 61 } 62 } 63 }; 64 Num s[2][101]; 65 66 Num que(int n,int k)//求n张牌,最多k个连续正面的情况 67 { 68 s[0][0].L=1; 69 int i=1; 70 while(i<=n) 71 { 72 s[0][i]=s[0][i-1]+s[1][i-1]; 73 if(i<=k) 74 { 75 s[1][i]=s[0][i-1]+s[1][i-1]; 76 } 77 if(i>k) 78 { 79 s[1][i]=s[0][i-1]+s[1][i-1]-s[0][i-k-1]; 80 } 81 i++; 82 } 83 return s[0][i-1]+s[1][i-1]; 84 } 85 86 int main() 87 { 88 int n,k; 89 while(cin >> n >> k) 90 { 91 Num q; 92 q.quan(n); 93 q=q-que(n,k-1);//相减得出至少k个正面的情况 94 q.display(); 95 } 96 return 0; 97 }