CF712D

Sol

不难想到暴力 DP,复杂度 \(O(tk^2)\),无法通过。

观察转移方程,注意到贡献到每个点的状态一定是连续的区间,那么用前缀和维护就好了。

偏移量可以设置的大一些以防 RE。

Code

#include <bits/stdc++.h>
#define x first
#define y second
#define pb push_back
#define pf push_front
#define desktop "C:\\Users\\incra\\Desktop\\"
#define IOS ios :: sync_with_stdio (false),cin.tie (0),cout.tie (0)
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
typedef pair <int,int> PII;
const int dx[] = {1,0,-1,0},dy[] = {0,-1,0,1};
template <typename T1,typename T2> bool tomax (T1 &x,T2 y) {
	if (y > x) return x = y,true;
	return false;
}
template <typename T1,typename T2> bool tomin (T1 &x,T2 y) {
	if (y < x) return x = y,true;
	return false;
}
LL power (LL a,LL b,LL p) {
	LL ans = 1;
	while (b) {
		if (b & 1) ans = ans * a % p;
		a = a * a % p;
		b >>= 1;
	}
	return ans;
}
int fastio = (IOS,0);
#define endl '\n'
#define puts(s) cout << (s) << endl
const int N = 400010,MOD = 1e9 + 7;
int a,b,k,n;
LL f[2][N],g[N];
LL ans1[N],ans2[N];
LL sum (int l,int r) {
    LL ans = g[min (r,N - 1)];
    if (l - 1 >= 0) ans = (ans - g[l - 1] + MOD) % MOD;
    return ans;
}
void solve (int a,LL ans[N]) {
    memset (f,0,sizeof (f)),memset (g,0,sizeof (g));
    f[0][a + (int)2e5] = 1;
    for (int i = 1;i <= n;i++) {
        memset (f[i & 1],0,sizeof (f[i & 1]));
        for (int j = 0;j < N;j++) g[j] = f[i - 1 & 1][j];
        for (int j = 1;j < N;j++) (g[j] += g[j - 1]) %= MOD;
        for (int j = 0;j < N;j++) f[i & 1][j] = sum (j - k,j + k);
    }
    for (int i = 0;i < N;i++) ans[i] = f[n & 1][i];
}
void mian () {
    cin >> a >> b >> k >> n;
    solve (a,ans1),solve (b,ans2);
    for (int i = 1;i < N;i++) (ans2[i] += ans2[i - 1]) %= MOD;
    LL ans = 0;
    for (int i = 1;i < N;i++) (ans += ans1[i] * ans2[i - 1] % MOD) %= MOD;
    cout << ans << endl;
}
int main () {
	int T = 1;
	// cin >> T;
	while (T--) mian ();
	return 0;
}
posted @ 2025-03-10 17:06  incra  阅读(12)  评论(0)    收藏  举报