首页 > 其他分享 >PKUWC2024 D1T2 补题记录

PKUWC2024 D1T2 补题记录

时间:2024-12-19 20:56:50浏览次数:3  
标签:ch const ll PKUWC2024 define 补题 mod dp D1T2

加深了一点点对同余最短路的理解。 link

考虑若对所有数 \(+1\),那么 \(f'_{1\dots n}\) 都会 \(+(n - 1)\),这启示我们可以根据最小值划分进行区间 dp。

设 \(dp_{l, r, V}\) 表示考虑数字 \(f_{l\dots r}\),区间 \(f'_{l\dots r}\) 中已经整体减 \(V\) 还是否能全部减成 \(0\)。

每次要么整体减一 \(dp_{l, r, V} \gets dp_{l, r, V - (r - l)}\),要么划分出一个最小值,位置为 \(i(l\le i < r)\),则 \(dp_{l, r, V} \gets dp_{l, i, V} \land dp_{i + 1, r, V}\)。

注意对于一个 \(V\) 模 \(r - l\) 的同余系,一定恰好存在一个分界线 \(p\) 满足 \(dp_{l, r, p} = 1\) 且 \(dp_{l, r, p + (r - l)} = 0\),因为我们可以无限地加 \(r - l\)。

这启示我们将第三维改为模 \(r - l\) 的余数,即设 \(dp_{l, r, u}\) 表示区间 \([l, r]\) 最多先整体减 \(V\) 合法且 \(V \equiv u \pmod {r - l}\),此时 \(V\) 的最大值。

这题关键在于如何合并 \(dp_{l, i, \_}\) 和 \(dp_{i + 1, r, \_}\) 两部分,枚举在经过了若干次外部整体加以及对 \([l, r]\) 加 \(r - l\) 的操作后,\(V\) 模 \(i - l\) 以及 \(r - i - 1\) 的余数分别为 \(v_1, v_2\),然后 exCRT 求出 \(\le \min(f_{l, i, v_1}, f_{i + 1, r, v_2})\) 且模 \(i - l\) 余 \(v_1\)、模 \(r - i - 1\) 余 \(v_2\) 的最大数。

设 \(t = \text{lcm}(i - l, r - i - 1)\),我们可以视为现在有个长度为 \(t\) 的环(不难发现左边操作 \(\frac t {r - i - 1}\) 次,右边操作 \(\frac t {i - l}\) 次后两边增量仍然相同)。

现在我们要变模数(将模 \(t\) 变为模 \(r - l\)),可以仿照 论战捆竹竿 的方法变模数。

  • 感觉自己理解得还不是很透彻,以后应该加训同于最短路部分。
点击查看代码
#include <bits/stdc++.h>

namespace Initial {
	#define ll int
	#define ull unsigned long long
	#define fi first
	#define se second
	#define mkp make_pair
	#define pir pair <int, int>
	#define pb push_back
	#define i128 __int128
	using namespace std;
	const ll maxn = 85, inf = 1e9, mod = 1e9 + 7;
	ll power(ll a, ll b = mod - 2) {
		ll s = 1;
		while(b) {
			if(b & 1) s = 1ll * s * a %mod;
			a = 1ll * a * a %mod, b >>= 1;
		} return s;
	}
	template <class T>
	const inline ll pls(const T x, const T y) { return x + y >= mod? x + y - mod : x + y; }
	template <class T>
	const inline void add(T &x, const T y) { x = x + y >= mod? x + y - mod : x + y; }
	template <class T>
	const inline void chkmax(T &x, const T y) { x = x < y? y : x; }
	template <class T>
	const inline void chkmin(T &x, const T y) { x = x > y? y : x; }
} using namespace Initial;

namespace Read {
	char buf[1 << 22], *p1, *p2;
//	#define getchar() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, (1 << 22) - 10, stdin), p1 == p2)? EOF : *p1++)
	template <class T>
	const inline void rd(T &x) {
		char ch; bool neg = 0;
		while(!isdigit(ch = getchar()))
			if(ch == '-') neg = 1;
		x = ch - '0';
		while(isdigit(ch = getchar()))
			x = (x << 1) + (x << 3) + ch - '0';
		if(neg) x = -x;
	}
} using Read::rd;

ll n, a[maxn], f[maxn][maxn][maxn], pos[maxn][maxn][maxn], minval[maxn];
ll b[maxn]; long long res[maxn];

void upd(ll *g, ll u1, ll u2) {
	ll z = u1; u1 %= u2; ll k = __gcd(u1, u2);
	for(ll i = 0; i < k; i++)
		for(ll j = i, c = 0; c < 2; j = (j - u1 + u2) % u2, c += (j == i))
			chkmax(b[j], b[(j + u1) % u2] - z);
}

void print(ll l, ll r, ll w) {
	if(l == r) return;
	ll x = r - l, u = w % x;
	if(pos[l][r][u] == l) {
		w = (a[l] - w) / x;
		res[l] += w, res[r] -= w;
		print(l + 1, r, a[l]);
	} else if(pos[l][r][u] == r) {
		w = (a[r] - w) / x;
		res[l] += w, res[r] -= w;
		print(l, r - 1, a[r]);
	} else {
		ll p = pos[l][r][u], c = 0;
		while(f[l][p][w % (p - l)] < w || f[p + 1][r][w % (r - p - 1)] < w)
			w += x, ++c;//, printf("D %d %d %d\n", l, r, w);
		res[l] += c, res[r] -= c;
		print(l, p, w), print(p + 1, r, w);
	}
}

void exgcd(ll a, ll b, ll &x, ll &y) {
	if(!b) { x = 1, y = 0; return; }
	exgcd(b, a % b, x, y);
	ll t = x; x = y;
	y = t - a / b * y;
}

signed main() {
	rd(n);
	for(ll i = 1; i <= n; i++) rd(a[i]);
	if(n == 1) return puts(a[1]? "No" : "Yes"), 0;
	memset(f, 0xcf, sizeof f);
	for(ll l = n; l; l--)
		for(ll r = l + 1; r <= n; r++) {
			ll d = r - l;
			if(r - l == 1) {
				if(a[l] == a[r])
					f[l][r][a[l] % d] = a[l], pos[l][r][a[l] % d] = l;
			} else {
				if(f[l + 1][r][a[l] % (d - 1)] >= a[l])
					f[l][r][a[l] % d] = a[l], pos[l][r][a[l] % d] = l;
				if(f[l][r - 1][a[r] % (d - 1)] >= a[r])
					f[l][r][a[r] % d] = a[r], pos[l][r][a[r] % d] = r;
			}
			for(ll i = l + 1; i < r - 1; i++) {
				ll g = __gcd(i - l, r - i - 1), t = (i - l) * (r - i - 1) / g;
				ll x, y; exgcd(i - l, r - i - 1, x, y);
				memset(b, 0xcf, sizeof b);
				for(ll u = 0; u < i - l; u++)
					for(ll v = 0; v < r - i - 1; v++) {
						if(f[l][i][u] < 0 || f[i + 1][r][v] < 0) continue;
						ll c = v - u; if(c % g) continue;
						ll lim = min(f[l][i][u], f[i + 1][r][v]);
						ll k = x * c / g, w = k * (i - l) + u;
						w = (w % t + t) % t, w += (lim - w) / t * t;
						if(w >= 0 && w <= lim) chkmax(b[w % d], w);
					}
				upd(b, t, r - l);
				for(ll u = 0; u < d; u++)
					if(b[u] > f[l][r][u]) f[l][r][u] = b[u], pos[l][r][u] = i;
			}
		}
	if(f[1][n][0] >= 0) {
		puts("Yes"), print(1, n, 0);
		for(ll i = 1; i < n; i++)
			printf("%lld ", res[i] += res[i - 1]);
	} else puts("No");
	return 0;
}

标签:ch,const,ll,PKUWC2024,define,补题,mod,dp,D1T2
From: https://www.cnblogs.com/Sktn0089/p/18617910

相关文章

  • (补题)Codeforces Round 993 (Div. 4) E.Insane Problem
    显然不可暴力解出,因此是到数学题。已知$$y=x*k^n$$所以我们可以利用y的区间范围$$[l1,r1]$$得出x的新的区间范围$$[l2/k^n(向上取整),r2/k^n(向下取整)]$$接着与原来的范围取交集然后不断枚举n即可,注意k^n不可能超过y#include<iostream>#defineintlonglongusingnamespa......
  • CF补题 991-Div
    CF补题991-Div.3-20241210Dashboard-CodeforcesRound991(Div.3)-CodeforcesA:题目大意:给出\(n\)个字符串,求前多少个字符串的大小之和小于\(m\)#include<iostream>#include<string>usingnamespacestd;stringa[52];intmain(){ intT; cin>>T; w......
  • icpc2024昆明补题记录
    D套娃这个trick是真没见过,也难怪场上没几个人过这个代码这么简单的题题目大意给定一排\(n\)个套娃,套娃的大小互不相同。你可以将相邻两个套娃套在一起,问最多能套几次?\[n≤10^5\]题解发现可以\(O(n)\)的判断一个长度为\(n\)的套娃序列是否能合并成一个,接下来从左边开始......
  • cf补题日记
    听退役选手建议,补40道C、D题。(又又又开新专题。。。进度:2/100 原题1:Youaregivenastring ss,consistingofdigitsfrom 00 to 99.Inoneoperation,youcanpickanydigitinthisstring,exceptfor 00 ortheleftmostdigit,decreaseitby 11,and......
  • CF补题 964-Div.4
    CF补题964-Div.4-20241206Dashboard-CodeforcesRound964(Div.4)-CodeforcesA:题目大意:给定一个两位数正整数n,求其位数之和#include<stdio.h>intmain(){intn;scanf("%d",&n);while(n--){intx,sum=0;scanf("%d&quo......
  • Codeforces Round 991 (Div. 3) G(补题)
    G-TreeDestruction Code:#include<bits/stdc++.h>usingnamespacestd;typedefint64_ti64;constintN=2e5+5;vector<int>adj[N];intdp[N],ans=0,n;voiddfs(intfrom,intfa){dp[from]=adj[from].size();ans=max......
  • 牛客小白月赛105 补题
    Blz的数字问题链接:B-lz的数字问题_牛客小白月赛105思路:多列举测试用例,考虑完整。首先判断是整数还是小数,小数分整数和小数两部分判断(函数调用最方便!)。注意有<小数的小数部分不够六位>的情况看个错误代码:tip(注释里):1.判断整数和小数应遍历整个数组,若出现".",则为小数,否则相反。......
  • coduck 复赛模拟赛三 补题报告 侯锦呈
    自测160分第一题30分第二题100分第三题30分(后来100分 自己改的)第四题0分第一题十五的月亮题目描述假设一个每个月都是30天,用0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1表示一个月30天中的月亮......
  • 2024CCPC山东省赛补题记录
    前言今天和队友VP了24CCPC山东省赛,最后9题,但是赛中7题左右我就隐身了,赛后看题解发现E题不难,赛时过的人太少导致有点畏手畏脚,看到题解一下就懂了,几分钟写好。这里主要补一下E和L的题解,这场比赛学到了维护区间信息,可以考虑把区间挂在线段树节点上,以及动态维护树直径的典。E传感器......
  • DAY3-补题
    一题之计在于补呐补题很快乐的一点就是看不懂且听不明白但是写注释中理解到了。果然学会一道题最简单的方式是给一个纯萌新讲。说在前面今天%你赛手感非常好,可能是换了一个位置的原因(玄首先T1没有读错题是一个比较大的进步,因为DAY1和2都是因为差不多这个原因寄掉了,读对题目果......