gym101669B Bricks SEERC2017

https://codeforces.com/gym/101669

即使DP式子再短,我还是想不到.jpg
这题关键想到是要枚举空位,f[i]为前i中的所有球已经放好了,且第i个为空格的方案数是多少

设s[i]为前i位的球的数量,那么前i位的空格总数就是i-s[i]了

由于M<=N,我们把n++,保证在n+1的位置处至少有一个空格,在那里统计算出答案。

只有每次s[i]==s[i-1]的时候,说明这里没有球直接下落,他可以作为一个空位,只有i-1-s[i-1]>=0时,f[i]才能有一个空位赋值为g[i-1-s[i-1]],g[i]表示之前已经有了i个空位的方案数,由于前i-1位已经有了g[i-1-s[i-1]]个空位了,自然吧方案数赋值给他。

否则如果不能为空位,那么f[i]=0

由于此时i多了一个空格,那么g[i-s[i]]也多处了f[i]种方案,加上就行了

看了看咖啡鸡和夜幕的另一种解法是维护一个offset偏移量+i-s[i]存在dp数组中,表示到i位置多了多少空格或者欠了多少空格的方案数,这样也是可以的

#include<bits/stdc++.h>
using namespace std;

const int maxl=1e6+10;
const int mod=1e9+7;

int n,m;
int s[maxl],f[maxl],g[maxl];

inline void prework()
{
	scanf("%d%d",&n,&m);
	++n;int x;
	for(int i=1;i<=m;i++)
	{
		scanf("%d",&x);
		s[x]++;
	}
	for(int i=1;i<=n;i++)
		s[i]+=s[i-1];
}

inline void mainwork()
{
	g[0]=1;
	for(int i=1;i<=n;i++)
	if(s[i]==s[i-1])
	{
		if(i-1-s[i-1]>=0)
		{ 
			f[i]=g[i-1-s[i-1]];
			g[i-s[i]]=(g[i-s[i]]+f[i])%mod;
		} 
	}
}

inline void print()
{
	printf("%d",f[n]);
}

int main()
{
	prework();
	mainwork();
	print();
	return 0;
}

猜你喜欢

转载自blog.csdn.net/liufengwei1/article/details/108946354