AtCoder Regular Contest 104 D(卡常)
阿新 • • 發佈:2020-10-04
考慮對每個x計算答案.
將除x以外的數都減去x,答案就是這些數的多重集(可以為空)和為0的方案數乘上(K+1), 最後加一個 k個 x
然而, t了6個點(別走Ψ( ̄∀ ̄)Ψ)
#include <bits/stdc++.h> #define all(n) (n).begin(), (n).end() #define se second #define fi first #define pb push_back #define mp make_pair #define sqr(n) (n)*(n) #define rep(i,a,b) for(int i=(a);i<=(b);++i) #define per(i,a,b) for(int i=(a);i>=(b);--i) #define IOS ios::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr) using namespace std; typedef unsigned long long ull; typedef long long ll; typedef unsigned long long ull; typedef pair<int, int> PII; typedef pair<ll, ll> PLL; typedef vector<int> VI; typedef double db; template<class T1, class T2> bool umin(T1& a, T2 b) { return a > b ? (a = b, true) : false; } template<class T1, class T2> bool umax(T1& a, T2 b) { return a < b ? (a = b, true) : false; } template<class T> void clear(T& a) { T().swap(a); } const int N = 1e2 + 5, M = 1e6 + 5; int n, m, _, k; ll f1[M], f2[M]; int main() { IOS; cin >> n >> k >> m; VI ans; f1[0] = f2[0] = 1; rep(i, 1, (n + 1) >> 1) { int l = (i - 1) * i / 2 * k, r = (n - i + 1) * (n - i) / 2 * k; rep(j, 1, l) f1[j] = 0; rep(j, 1, r) f2[j] = 0; rep(j, 1, i - 1) { int r = (j - 1) * j / 2 * k, d = j * k; rep(s, j, r) f1[s] = (f1[s] + f1[s - j]) % m; per(s, r, d + j) f1[s] = (f1[s] + m - f1[s - d - j]) % m; } rep(j, 1, n - i) { int r = (j - 1) * j / 2 * k, d = j * k; rep(s, j, r) f2[s] = (f2[s] + f2[s - j]) % m; per(s, r, d + j) f2[s] = (f2[s] + m - f2[s - d - j]) % m; } ll res = k; per(s, min(l, r), 1) res = (res + f1[s] * f2[s] % m * (k + 1) % m) % m; ans.pb(res); } for (auto i : ans) cout << i << '\n'; per(i, ans.size() - 1 - (n & 1), 0) cout << ans[i] << '\n'; return 0; }
然而還可以優化, 思路是一樣的, 直接把左右區間寫成一個區間, 偏移量嘛
假定把 x 左邊全部選上,也就是現在是最小值, 左區間全部-x(都是負數), 對於1~N(除了x), 選擇 1~x-1, 相當於把最開始選擇左區間的數扔掉了, ++a, 選擇右區間, 也是 ++a是不是少了一個常數啊?
//對於 1e8小個常數是優化是相當高的
#include <bits/stdc++.h> #define all(n) (n).begin(), (n).end() #define se second #define fi first #define pb push_back #define mp make_pair #define sqr(n) (n)*(n) #define rep(i,a,b) for(int i=(a);i<=(b);++i) #define per(i,a,b) for(int i=(a);i>=(b);--i) #define IOS ios::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr) using namespace std; typedef unsigned long long ull; typedef long long ll; typedef unsigned long long ull; typedef pair<int, int> PII; typedef pair<ll, ll> PLL; typedef vector<int> VI; typedef double db; template<class T1, class T2> bool umin(T1& a, T2 b) { return a > b ? (a = b, true) : false; } template<class T1, class T2> bool umax(T1& a, T2 b) { return a < b ? (a = b, true) : false; } template<class T> void clear(T& a) { T().swap(a); } const int N = 1e2 + 5, M = 1e6; int n, m, _, k; int a[M << 1], *f; void add(int& x, int y){ x += y; if(x >= m) x -= m; } void sub(int& x, int y){ x -= y; if(x < 0) x += m; } int main() { IOS; cin >> n >> k >> m; VI ans; f = a + M; rep(i, 1, (n + 1) >> 1) { int l = -(i - 1) * i / 2 * k, r = (n - i + 1) * (n - i) / 2 * k; rep(j, l, r) f[j] = 0; f[l] = 1; //左區間全選 VI res; rep(j, 1, n) if (i != j) res.pb(abs(j - i)); //都是++a sort(all(res)); r = l; for (int x : res) { int d = x * k; r += d; rep(j, l + x, r) add(f[j], f[j - x]); per(j, r, l + x + d) sub(f[j], f[j - d - x]); } ans.pb(((ll)f[0] * (k + 1) - 1 + m) % m); } rep(i, (n + 1 >> 1) + 1, n) ans.pb(ans[n - i]); for (int i : ans) cout << i << '\n'; return 0; }