[ AT_agc009_c]Division into Two

题目传送门

大家都知道集合吧,原谅我喜欢说废话

解法

先钦定 A > B A>B A>B,
先把数排好序得到数组 a a a,考虑先解决集合 X X X的问题,

设计状态:

明显只有一维( n < = 1 e 5 n<=1e5 n<=1e5),所以有:
f i : X 集合最后放的是第 i 个数,对于前 i 个数来说 X , Y 都合法的方案数 f_i:X集合最后放的是第i个数,对于前i个数来说X,Y都合法的方案数 fi:X集合最后放的是第i个数,对于前i个数来说X,Y都合法的方案数
发现后 ( n − i ) (n-i) ni个放在 Y Y Y的数我们未保证合法,但是我们之后特判一下就好了

状态转移

f i f_i fi f j f_j fj转移而来
考虑有哪些 j j j可以贡献:
1. i > j i>j i>j(废话)
2. a i − a j ≥ A a_i-a_j\ge A aiajA(差值大于 A A A)
3. max ⁡ { a k − a k − 1 } ≥ B , k ∈ ( j , i ) \max\{a_k-a_{k-1}\}\ge B,k\in(j,i) max{akak1}B,k(j,i)(满足 Y Y Y集合的要求)
则: f i = ∑ f j f_i=\sum f_j fi=fj

code:

#include 
#include 
using namespace std;
typedef long long ll;
const int mod = 1e9 + 7,N=1e5+7;
int n,l,r;
int f[N],sum[N];
ll A,B;
ll a[N];
int main(){
	scanf("%d%lld%lld",&n,&A,&B);
	if(A=A) r++;
		if(l<=r) {
			f[i]=(1ll*f[i]+1ll*sum[r])%mod;
			if(l) f[i]=(1ll*f[i]-1ll*sum[l-1]+mod)%mod;
		}
		sum[i]=(1ll*sum[i-1]+1ll*f[i])%mod;
		if(a[i]-a[i-1]

TXL

你可能感兴趣的:(计数DP,c语言,算法,动态规划)