来自学长的馈赠1

首先感谢学长

A. Alice

打表好题, 通过打表可以发现就是判断两个数\(lowbit\)是否相等

实测\(cin\)\(cout\)不如\(scanf\)\(printf\)(血的教训)

code
#include<cstring>
#include<cstdio>
using namespace std;
int lowbit(int x){return x & -x;}
int main(){
    int T;scanf("%d",&T);
    for(int i = 1; i <= T; ++i){
        int a, b;scanf("%d%d",&a,&b);
        if(lowbit(a) == lowbit(b))printf("B\n");
        else printf("A\n");
    }
    return 0;
}

B. Box

题解写的很好,直接粘过来了

image

里面那个容易证明,其实是\(minmax\)容斥

\(m + m / (m + 1) * m\)和后面那个类似的式子,可以这样理解一下

放下\(m\)个当前颜色球,会有\(m + 1\)个空位,有\(m\)个对答案有贡献,一共需要插进去\(m\)个。

关于线性求逆优化,简单来说就是一个前缀积,类似求阶乘逆元那样,具体看代码吧

code
#include<cstdio>
#include<cstring>
using namespace std;
typedef long long ll;
const int mod = 998244353;
const int maxn = 2e7 + 55;
int fac[maxn], finv[maxn], s[maxn], a[maxn],iv[maxn], sv[maxn], n, m;
int qpow(int x, int y){
	int ans = 1;
	for(;y ; y >>= 1, x = 1ll * x * x % mod)if(y & 1)ans = 1ll * ans * x % mod;
	return ans;
}
int c(int n, int m){return 1ll * fac[n] * finv[m] % mod * finv[n - m] % mod;}
int main(){
	scanf("%d%d", &n, &m);
	fac[0] = 1;
	for(int i = 1; i <= n; ++i)
		fac[i] = 1ll * fac[i - 1] * i % mod;
	finv[n] = qpow(fac[n], mod - 2);
	for(int i = n - 1; i >= 1; --i)finv[i] = 1ll * finv[i + 1] * (i + 1) % mod;
	finv[0] = 1;
	for(int i = 1; i <= n; ++i)a[i] = (1ll * m * i + 1) % mod;
	s[0] = 1;
	for(int i = 1; i <= n; ++i)s[i] = 1ll * a[i] * s[i - 1] % mod;
	sv[n] = qpow(s[n], mod - 2);
	for(int i = n - 1; i >= 1; --i)sv[i] = 1ll * sv[i + 1] * a[i + 1] % mod;
	iv[1] = sv[1];
	for(int i = 2; i <= n; ++i)iv[i] = 1ll * sv[i] * s[i - 1] % mod;
	int ans = 0;
	for(int i = 1; i <= n; ++i){
		if(i & 1)ans = (ans + (1ll * c(n, i) * ((1ll * m * i % mod + 1ll * m * i % mod * iv[i] % mod * m % mod * (n - i) % mod) % mod) % mod) )% mod;
		else ans = ((ans - 1ll * c(n, i) * ((1ll * m * i % mod + 1ll * m * i % mod * iv[i] % mod * m % mod * (n - i) % mod) % mod) % mod ) % mod + mod ) % mod;
	}
	printf("%d\n", ans);
	return 0;
}

C. Common

这是一道常规套路题

确实比较套路

默认\(a[0][0] = 1\), 那么如果令\(a[-b[i]][-c[i]] = 1\)的话,对于任意\(a[b[j]][c[j]]\)他的值其实是\(a[b[i]+b[j]][c[i]+c[j]]\)

然后就可以把\(a[-b[i]][-c[i]]\)全加一,然后按照式子递推一遍即可

code
#include<iostream>
#include<cstring>
using namespace std;
typedef long long ll;
const int maxn = 4055;
const int o = 2005;
const int mod = 998244353;
int rem[maxn][maxn];
int n, t1, t2, t3, mb, mc;
int b[1000005], c[1000005];
int main(){
	scanf("%d%d%d%d", &n, &t1, &t2, &t3);
	for(int i = 1; i <= n; ++i)scanf("%d", &b[i]);
	for(int i = 1; i <= n; ++i)scanf("%d", &c[i]);
	for(int i = 1; i <= n; ++i)mb = max(mb, b[i]);
	for(int i = 1; i <= n; ++i)mc = max(mc, c[i]);
	for(int i = 1; i <= n; ++i)++rem[o - b[i]][o - c[i]];
	for(int i = o - mb; i <= o + mb ; ++i){
		for(int j = o - mc; j <= o + mc; ++j){
			rem[i][j] = (rem[i][j] + 1ll * t1 * rem[i - 1][j]  % mod + 1ll * t2 * rem[i][j - 1] % mod + 1ll * t3 * rem[i - 1][j - 1] % mod) % mod;
		}
	}
	int ans = 0;
	for(int i = 1; i <= n; ++i)ans = (ans + rem[o + b[i]][o + c[i]]) % mod;
	printf("%d\n", ans);
	return 0;
}

D. Do not ak

分块+卡常,洛谷至今没卡过

题解看洛谷吧P5046

code
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<iostream>
#define block(x) (((x) - 1) / len + 1)
#define bl(x) (((x) - 1) * len + 1)
#define br(x) min(n, x * len)
using namespace std;
typedef long long ll;
const int maxn = 1e5 + 55;
const int maxb = 505;
inline int read(){
	int x = 0; char c;c = getchar();
	while(c < '0' || c > '9')c = getchar();
	while(c >= '0' && c <= '9')x = (x << 3) + (x << 1) + (c ^ 48), c = getchar();
	return x;
}
int n, m, a[maxn], len, pre[maxn], suf[maxn], pres[maxn], tong[maxn], cntl[maxb][maxn], cntr[maxb][maxn];
ll ansl[maxb][maxn], ansr[maxb][maxn];
struct note{
	int val, pos;
	friend bool operator < (note x, note y){
		return x.val < y.val;
	}
}b[maxn];
struct tree{
	int t[maxn];
	int lowbit(int x){return x & -x;}
	void add(int x, int d){while(x <= n){t[x] += d;x += lowbit(x);}}
	int query(int x){int ans = 0;while(x){ans += t[x]; x -=lowbit(x);} return ans;}
}T;
int x[maxn], y[maxn], cx, cy;
int merg(){
	int p1 = 1, p2 = 1, ans = 0;
	while(p1 <= cx && p2 <= cy)
	  if(x[p1] < y[p2]) ++p1; else ans += cx - p1 + 1, ++p2;
	return ans;
}
int main(){
	n = read(), m = read(); len = 500;
	for(register int i = 1; i <= n; ++i)a[i] = read();
	for(register int i = 1; i <= n; ++i)b[i].val = a[i], b[i].pos = i;
	int ks = block(n);
	for(register int i = 1; i <= ks; ++i){
		int l = bl(i), r = br(i);
		sort(b + l, b + r + 1);
		for(register int j = l; j <= r; ++j)pre[j] = j - l - T.query(a[j]), T.add(a[j], 1);
		for(register int j = l; j <= r; ++j)T.add(a[j], -1);
		for(register int j = r; j >= l; --j)suf[j] = T.query(a[j]), T.add(a[j], 1);
		for(register int j = l; j <= r; ++j)T.add(a[j], -1);
		pres[l] = pre[l];
		for(register int j = l + 1; j <= r; ++j)pres[j] = pre[j] + pres[j - 1];
	}
	for(register int i = 1, nb = 1; i <= n; ++i){
		++tong[a[i]];
		if(i == br(nb)){
			for(register int j = 1; j <= n; ++j)cntl[nb][j] = cntl[nb][j - 1] + tong[j];
			for(register int j = n; j >= 1; --j)cntr[nb][j] = cntr[nb][j + 1] + tong[j];
			++nb;
		}
	}
	for(register int i = 1; i <= ks; ++i)
		for(register int j = bl(i); j <= n; ++j)
			ansr[i][j] = ansr[i][j - 1] + cntr[block(j) - 1][a[j] + 1] - cntr[i - 1][a[j] + 1] + pre[j];
	for(register int i = 1; i <= ks; ++i)
		for(register int j = br(i); j >= 1; --j)
			ansl[i][j] = ansl[i][j + 1] + cntl[i][a[j] - 1] - cntl[block(j)][a[j] - 1] + suf[j];
	ll ans = 0;
	for(register int ask = 1; ask <= m; ++ask){
		int l, r; l = read(), r = read();
		l ^= ans; r ^= ans;
		if(l > r)swap(l, r);
		ans = 0;
		cx = cy = 0;
		int kl = block(l), kr = block(r);
		if(kl == kr){
			for(register int i = bl(kl); i <= br(kl); ++i)
			  if(l <= b[i].pos && b[i].pos <= r)y[++cy] = b[i].val;
			  else if(b[i].pos < l)x[++cx] = b[i].val;
			ans = pres[r] - (l == bl(kl) ? 0 : pres[l - 1]) - merg(); 
		}else{
			ans = ansl[kr - 1][l] + ansr[kl + 1][r] - ansl[kr - 1][bl(kl + 1)];
			for(register int i = bl(kl); i <= br(kl); ++i)if(b[i].pos >= l)x[++cx] = b[i].val; 
			for(register int i = bl(kr); i <= br(kr); ++i)if(b[i].pos <= r)y[++cy] = b[i].val;
			ans += merg();
		}
		printf("%lld\n",ans);
	}
	return 0;
}
posted @ 2022-07-20 08:14  Chen_jr  阅读(31)  评论(0编辑  收藏  举报