马上注册,结交更多好友,享用更多功能^_^
您需要 登录 才可以下载或查看,没有账号?立即注册
x
总结与反思
B - 对于求权值总和 / 乘积 等于定值要想到背包dp C - sgt 维护的值看看是否冗余, 只需要单点修改的东西不需要进入 up 和 dn
B - ppip 数列
ppip看到了一个各元素均为正整数、长度为k、各元素之和为n的不降数列。
他想要知道这种数列的个数,对998244853取模。
转化为 权值为 1 - k 的物品, 不限制取的个数, 总和为 n 的方案数, 转化为完全背包问题
在遇到【不易处理的限制】与【就算有限制也很好处理,可惜没限制】的问题时,可以通过转转转将其转化。
原本横向的性质,在新问题上必须纵向考虑。
对于有关【整数】、【重复】等的问题,可考虑将【有无】与【数量之差】相互转化。f[0] = 1;
cin >> n >> k;
n -= k;
for (int i = 1; i <= k; i++) {
for (int j = i; j <= n; j++) {
f[j] = (f[j] + f[j - i]) % P;
}
}
cout << f[n];
D - P4472 [BJWC2018] 八维
倍增, 哈希#include <bits/stdc++.h>
using namespace std;
typedef unsigned long long ll;
typedef pair<int, int> pii;
const int N = 505;
const ll B = 233;
const int dx[] = {-1, -1, -1, 0, 0, 1, 1, 1};
const int dy[] = {-1, 0, 1, -1, 1, -1, 0, 1};
char s[N][N];
int n, m, K;
ll p[N], f[N][N][30];
long long same, all;
pii g[N][N][30];
unordered_map<ll, int> cnt;
int main(){
ios::sync_with_stdio(0);
cin.tie(0);
cin >> n >> m >> K;
for(int i = 0; i < n; i++){
cin >> s[i];
}
int lim = log2(K);
p[0] = B;
for(int i = 1; i <= lim; i++){
p[i] = p[i - 1]*p[i - 1];
}
for(int d = 0; d < 8; d++){
// 录入 f, g
for(int i = 0; i < n; i++){
for(int j = 0; j < m; j++){
f[i][j][0] = s[i][j];
g[i][j][0] = make_pair((i + dx[d] + n) % n, (j + dy[d] + m) % m);
}
}
// 倍增
for(int k = 1; k <= lim; k++){
for(int i = 0; i < n; i++){
for(int j = 0; j < m; j++){
int x = g[i][j][k - 1].first;
int y = g[i][j][k - 1].second;
f[i][j][k] = f[i][j][k - 1]*p[k] + f[x][y][k - 1];
g[i][j][k] = g[x][y][k - 1];
}
}
}
for(int i = 0; i < n; i++){
for(int j = 0; j < m; j++){
ll hash = 0;
auto cur = make_pair(i, j);
for(int k = lim; k >= 0; k--){
if((K >> k) & 1){
hash = hash*p[k] + f[cur.first][cur.second][k];
cur = g[cur.first][cur.second][k];
}
}
cnt[hash]++;
}
}
}
for(auto v : cnt){
same += 1ll*v.second*v.second;
}
all = 64ll*n*n*m*m;
cout << same / __gcd(same, all) << '/' << all / __gcd(same, all);
return 0;
}
|