前缀和&差分
C - K-bonacci
为了防止出现负数一般都要加上mod再%mod
为什么会出现负数呢? 因为在取模运算中会出现把大值模成小值端点情况,两个数之间的大小不能确定
#include<bits/stdc++.h>
using namespace std;
#define endl '\n'
//#define ll long long
#define int long long
#define pii pair<int, int>
#define fi first
#define se second
#define vi vector<int>
#define lowbit(x) (x & (-x))
const int N = 500, mod = 1e9, inf = 0x3f3f3f3f;
void solve() {
int n, k, sum = 0; cin >> n >> k; vi a(n + 1);
if(n < k){cout << "1\n"; return ;}
a[0] = 1;
for(int i = 1; i <= k; ++i)a[i] = a[i - 1] + 1;
for(int i = k + 1; i <= n + 1; ++i)
a[i] = ((a[i - 1] - a[i - k - 1] + mod) % mod + a[i - 1]) % mod;
cout << (a[n + 1] - a[n] + mod) % mod << endl;
}
signed main() {
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int T = 1;
//cin >> T;
while (T--) solve();
return 0;
}
整点正方形计数2 - Problem - QOJ.ac
枚举 + 差分
种类数是 O(min(n,m)^2)
对于矩形区域 (x1,y1) 到 (x2,y2) 整体加 delta,二维差分的标记规则是:
- 在左上角
(x1,y1)处+delta - 在右上角
(x1,y2+1)处-delta - 在左下角
(x2+1,y1)处-delta - 在右下角
(x2+1,y2+1)处+delta
![[2ac9e3cf496afcce76af95944399fb95 1.jpg]]
#include<bits/stdc++.h>
using namespace std;
#define endl '\n'
#define int long long
#define vc vector<char>
#define vi vector<int>
#define vii vector<vi>
#define lowbit(x) ((x) & (-x))
const int N = 2e3 + 100;
void solve(){
int n, m; cin >> n >> m;
++m, ++n;//从n x m 的画布其实是
vii g(n + 1, vi(m + 1));
for(int a = 0; a < min(n, m); ++a)//遍历每个向量的长度,然后去找这个向量形成的正方形能的四个顶点在画布中存在的最大范围边界
for(int b = 1; a + b < min(n, m); ++b){
auto work = [&](int l, int u) -> void{
int r = m - a - b + l, d = n - b - a + u;//二维差分标记规则,在(x2 + 1, y2 + 1)处标记,n ++, m ++后就不用再 r 和 d 处 + 1了
++g[u][l];
--g[u][r];
--g[d][l];
++g[d][r];
};
work(b, 0);//1
work(0, a);//2
work(a, a + b);//3
work(a + b, b);//4
}
for(int i = 0; i < n; ++i)
for(int j = 0; j < m; ++j){
if(i) g[i][j] += g[i - 1][j];
if(j) g[i][j] += g[i][j - 1];
if(i && j)g[i][j] -= g[i - 1][j - 1];
cout << g[i][j] << " \n"[j == m - 1];
}
}
signed main(){
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int T = 1;
// cin >> T;
while(T--)solve();
return 0;
}

浙公网安备 33010602011771号