VP 9.24 AtCoder Regular Contest 075

找了一场偏水的 ARC 打了打。

20 分钟内干完了 CDE,只剩下 F 了,然后想了一会儿,会了,但是被叫出去叉 c7 中秋联考的 std 去了,回来的时候就已经 VP 结束了,后来 WA 了 114514 发后,终于调完了(虽然下了几发数据)。

C Bugged

简单背包即可。

D Widespread

考虑二分,然后简单 check 一下。

E Meaningful Mean

小套路题,每个数先减 k ,然后就转化为求 \(>0\) 的子段个数,树状数组维护即可。

F Mirrored

拿到题 :woc ,什么鬼?

想了一会儿 :好像只有 \(D \bmod 9 = 0\) 有解?

后来 :我会了!!!

中途出去然后回来后:写完了! WA 了!

WA 了 114514 后 :下了 \(inf\) 组数据,终于调完了。


首先枚举位数 \(l\),只要我们确定了前 \(\left\lceil\frac{l}{2}\right\rceil\) 位,那么就全部确定了,设 \(n_i\) 表示 \(n\) 的第 \(i\) 位的数,那么我们最后 \(rev(n) - n\) 则是 :

\[\sum\limits_{i = 1}^{\left\lfloor\frac{l}{2}\right\rfloor} (n_i - n_{l - i + 1}) \times (10 ^ {l - i + 1} - 10 ^ i) \]

考虑枚举 \(n_i - n_{l - i + 1}\) ,使得最后这个柿子为 \(D\) 即可,这个可以用爆搜,方案简单算一算就行了。

但是很可能会 TLE,考虑减枝:

当还要凑出来的值已经 \(>\) 之后最大可以凑出来的值 或者 还要凑出来的值已经 \(<\) 之后最小可以凑出来的值,则 return 0

关于复杂度 :

因为当 \(l -1\) 后, \(10 ^ {l - i + 1} - 10 ^ i\) 大概会 \(\div10\) ,那么每次递归下去的有用的叉不会大于 \(2\) ,因此单次 dfs 复杂度不超过 \(\mathcal O(2^l)\)

code:

#include <bits/stdc++.h>

#define in read()
#define rep(i, x, y) for(int i = (x); i <= (y); i++)
#define per(i, x, y) for(int i = (x); i >= (y); i--)

using namespace std;

typedef long long ll;

ll pw[35], mx[35], stk[35], ans, v[35];
int cnt, D;

ll dfs(int x, ll res) {
	if(x == cnt + 1) {
		if(res == 0) return 1;
        return 0;
	}
	if(res > mx[x] || res < -mx[x]) return 0;
	ll t = 0;
	rep(i, 0, 9) {
		int cho = 10 - i; if(x == 1) cho--; 
		v[x] = -i;
		if(cho > 0) t += dfs(x + 1, res - stk[x] * i) * cho;
		cho = 10 - i;
		if(i == 0) continue; v[x] = i;
		if(cho > 0) t += dfs(x + 1, res + stk[x] * i) * cho;
	} return t;
}

int main() {
    D = in;
    pw[0] = 1; rep(i, 1, 33) pw[i] = pw[i - 1] * 10;
	rep(i, 1, 17) {
		int l = 0, r = i; cnt = 0;
		while(l < r) {
			stk[++cnt] = pw[r] - pw[l];
			r--; l++;
		}
		mx[cnt + 1] = 0;
		per(j, cnt, 1) mx[j] = mx[j + 1] + stk[j] * 9;
		ans += dfs(1, D) * (i & 1 ? 1 : 10);
	}
	cout << ans << endl;
}
posted @ 2021-09-24 17:34  Werner_Yin  阅读(45)  评论(0编辑  收藏  举报