XTU 1233 Coins(DP)
题意: n个硬币摆成一排,问有连续m个正面朝上的硬币的序列种数。
很明显的DP题。定义状态dp[i][1]表示前i个硬币满足条件的序列种数。dp[i][0]表示前i个硬币不满足条件的序列种数。
那么显然有dp[i][1]=dp[i-1][1]*2+dp[i-1-m][0].
如果前i-1个硬币满足条件,那么第i个硬币无论怎么样都满足条件。如果前i-1-m个硬币不满足条件,那么只需要再添加m个正面朝上的硬币即可。
dp[i][0]=2^i-dp[i][1].
于是最后的答案就是dp[n][1].
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
# include <cstdio> # include <cstring> # include <cstdlib> # include <iostream> # include <vector> # include <queue> # include <stack> # include <map> # include <set> # include <cmath> # include <algorithm> using namespace std; # define lowbit(x) ((x)&(-x)) # define pi acos(-1.0) # define eps 1e-7 # define MOD 1000000007 # define INF 1000000000 # define mem(a,b) memset(a,b,sizeof(a)) # define FOR(i,a,n) for(int i=a; i<=n; ++i) # define FO(i,a,n) for(int i=a; i<n; ++i) # define bug puts("H"); # define lch p<<1,l,mid # define rch p<<1|1,mid+1,r # define mp make_pair # define pb push_back typedef pair<int,int> PII; typedef vector<int> VI; # pragma comment(linker, "/STACK:1024000000,1024000000") typedef long long LL; int Scan() { int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } void Out(int a) { if(a<0) {putchar('-'); a=-a;} if(a>=10) Out(a/10); putchar(a%10+'0'); } const int N=1000005; //Code begin... LL dp[N][2], p[N]; void init(){p[0]=1; FO(i,1,N) p[i]=p[i-1]*2%MOD;} int main () { int T, n, m; scanf("%d",&T); init(); while (T--) { scanf("%d%d",&n,&m); mem(dp,0); dp[m][1]=1; dp[m][0]=((p[m]-dp[m][1])%MOD+MOD)%MOD; FO(i,0,m) dp[i][0]=p[i]; FOR(i,m+1,n) dp[i][1]=(dp[i-1][1]*2+dp[i-1-m][0])%MOD, dp[i][0]=((p[i]-dp[i][1])%MOD+MOD)%MOD; printf("%lld\n",dp[n][1]); } return 0; }