窗口dp|组合数学
lc3428
贡献法+组合数学
const int MOD = 1'000'000'007;
const int MX = 100'000;
long long F[MX]; // F[i] = i!
long long INV_F[MX]; // INV_F[i] = i!^-1
long long pow(long long x, int n) {
long long res = 1;
for (; n; n /= 2) {
if (n % 2) {
res = res * x % MOD;
}
x = x * x % MOD;
}
return res;
}
auto init = [] {
F[0] = 1;
for (int i = 1; i < MX; i++) {
F[i] = F[i - 1] * i % MOD;
}
INV_F[MX - 1] = pow(F[MX - 1], MOD - 2);
for (int i = MX - 1; i; i--) {
INV_F[i - 1] = INV_F[i] * i % MOD;
}
return 0;
}();
long long comb(int n, int m) {
return F[n] * INV_F[m] % MOD * INV_F[n - m] % MOD;
}
class Solution {
public:
int minMaxSums(vector<int>& nums, int k) {
ranges::sort(nums);
int n = nums.size();
long long ans = 0;
for (int i = 0; i < n; i++) {
long long s = 0;
for (int j = 0; j < min(k, i + 1); j++) {
s += comb(i, j);
}
ans = (ans + s % MOD * (nums[i] + nums[n - 1 - i])) % MOD;
}
return ans;
}
};
错误的思路
eg. 1 2 3
会漏算1,3这个子序列
class Solution {
const int MOD = 1e9 + 7;
public:
int minMaxSums(vector<int>& nums, int k) {
int n = nums.size();
long long ans = 0;
vector<long long> pow2(n, 1);
for (int i = 1; i < n; ++i) {
pow2[i] = (pow2[i - 1] * 2) % MOD;
}
sort(nums.begin(), nums.end());
for (int i = 0; i < n; ++i) {
for (int j = i; j < n; ++j) {
int len = j - i + 1;
if (len > k) continue;
long long cnt = (j == i) ? 1 : pow2[j - i - 1];
ans = (ans + (nums[i] + nums[j]) * cnt) % MOD;
}
}
return ans;
}
};
lc1871
到 i 更新窗口+dp
if (s[i] == '0' && cnt > 0)
dp[i] = true;//到 i 更新窗口
if (i >= maxJump && dp[i - maxJump])
--cnt;

class Solution {
public:
bool canReach(string s, int minJump, int maxJump) {
int n = s.size();
vector<bool> dp(n, false);
dp[0] = true;
int cnt = 1; //滑窗cnt初始化,一开始i = 0是可达的,所以cnt初始化为1
for (int i = minJump; i < n; ++i)
{
if (s[i] == '0' && cnt > 0)
dp[i] = true;
//到 i 更新窗口
if (i >= maxJump && dp[i - maxJump])
--cnt;
if (dp[i - minJump + 1])
++cnt;
}
return dp[n - 1];
}
};
