2022NOIP A层联测32

A. 行走

按照颜色考虑,然后发现是 \(excrt\)

考场重新发明 \(excrt\)

但是炸了 \(long long\)

而且 \(k\) 没有取到最小整数解

code
#include<bits/stdc++.h>
using namespace std;

typedef __int128_t ll;
typedef unsigned long long ull;
typedef pair<int, int> pii;

ll read(){
	ll x = 0; char c = getchar();
	while(!isdigit(c))c = getchar();
	do{x = x * 10 + (c ^ 48); c = getchar();}while(isdigit(c));
	return x;
}

const int maxn = 250005;
int n, m, s[maxn];
vector<ll>a[maxn], b[maxn], t, lc;
ll exgcd(ll a, ll &x, ll b, ll &y){
	if(b == 0){x = 1; y = 0; return a;}
	ll g = exgcd(b, y, a % b, x);
	y = y - a / b * x; return g;
}
void sol(ll col){
	ll x, lcm;
	x = a[col].back(), lcm = b[col].back();
	a[col].pop_back(); b[col].pop_back();
	for(int i = 0; i < n - 1; ++i){
		ll k1, k2; ll g = exgcd(lcm, k1, b[col].back(), k2);
		ll c = x - a[col].back();
		if(c % g)return;
		lcm /= g; k2 = (k2 % lcm * (c / g) % lcm + lcm) % lcm;
		lcm = lcm * b[col].back();
		x = (k2 * b[col].back() % lcm + lcm + a[col].back()) % lcm; 
		a[col].pop_back(); b[col].pop_back();
	}
	x = (x % lcm + lcm) % lcm;
	t.push_back(x); lc.push_back(lcm);
}

ll calc(ll l){
	ll ans = 0;
	int s = t.size();
	for(int i = 0; i < s; ++i)ans += l / lc[i] + (l % lc[i] > t[i]);
	return ans;
}
ll l, r;
int main(){
	freopen("walk.in","r",stdin);
	freopen("walk.out","w",stdout);
	n = read(), m = read(), l = read(), r = read();
	--l; --r;
	for(int i = 1; i <= n; ++i){
		s[i] = read();
		for(int j = 0; j < s[i]; ++j){
			int col = read();
			a[col].push_back(j);
			b[col].push_back(s[i]);
		}
	}
	for(int i = 0; i <= m; ++i)if((int)b[i].size() == n)sol(i);
	printf("%lld\n",(long long)calc(r) - (long long )calc(l - 1));
	return 0;
}

B. 鸟之诗

简单容斥一下

code
#include<bits/stdc++.h>
using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pii;

ll read(){
	ll x = 0; char c = getchar();
	while(!isdigit(c))c = getchar();
	do{x = x * 10 + (c ^ 48); c = getchar();}while(isdigit(c));
	return x;
}

const int maxn = 2000006;
const int mod = 998244353;
ll qpow(ll x, ll y){
	if(x < 0)return 0;
	ll ans = 1;
	for(; y; y >>= 1, x = 1ll * x * x % mod)if(y & 1)ans = 1ll * ans * x % mod;
	return ans;
}
ll n, m, a[maxn], b[maxn];
int main(){
	freopen("air.in","r",stdin);
	freopen("air.out","w",stdout);
	m = read(), n = read() % (mod - 1);
	for(int i = 1; i <= m; ++i)a[i] = read();
	for(int i = 1; i <= m; ++i)b[i] = read();
	ll ans = 1;
	for(int i = 1; i <= m; ++i){
		if(a[i] > b[i])ans = 0;
		if(a[i] < b[i]){
			ans = 1ll * ans * (((qpow(b[i] - a[i] + 1, n) - 2 * qpow(b[i] - a[i], n) + qpow(b[i] - a[i] - 1, n)) % mod + mod ) % mod) % mod;
		}
	}
	printf("%lld\n",ans);
	return 0;
}

C. 核心共振

一看这种题就直接放弃了。。。。

最后时间不够,暴力都没打对

粘一下题解,感觉挺妙的

image

code
#include<bits/stdc++.h>
using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pii;

ll read(){
	ll x = 0; char c = getchar();
	while(!isdigit(c))c = getchar();
	do{x = x * 10 + (c ^ 48); c = getchar();}while(isdigit(c));
	return x;
}
int mod, p;
const int maxn = 2e7 + 5555;
int fac[maxn], inv[maxn];
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;
}
void init(int mx){
	fac[0] = inv[0] = 1; for(int i = 1; i <= mx; ++i)fac[i] = 1ll * fac[i - 1] * i % mod;
	inv[mx] = qpow(fac[mx], mod - 2); for(int i = mx - 1; i >= 1; --i)inv[i] = 1ll * inv[i + 1] * (i + 1) % mod;
}
int c(ll n, ll m) {
	if(n < m || n < 0 || m < 0)return 0;
	if(n >= p || m >= p)return 1ll * c(n / p, m / p) * c(n % p, m % p) % mod;
	return 1ll * fac[n] * inv[m] % mod * inv[n - m] % mod;
}
int f(ll n, ll m){
	if(m < p){
		int ans = 0;
		for(int i = 0; i <= m; ++i)ans = (ans + c(n, i)) % mod;
		return ans;
	}
	int ans = 0;
	for(int i = 0; i < p; ++i)ans = (ans + c(n % p, i)) % mod;
	ans = 1ll * ans * f(n / p, m / p - 1) % mod;
	int res = 0;
	for(int i = 0; i <= m % p; ++i)res = (res + c(n % p, i)) % mod;
	res = 1ll * res * c(n / p, m / p) % mod;
	return (ans + res) % mod;
}
ll n, m;
int main(){
	freopen("dimension.in","r",stdin);
	freopen("dimension.out","w",stdout);
	n = read(), m = read(), p = mod = read();
	init(mod - 1);
	printf("%d\n", (f(n + 1, m + 1) + mod - 1) % mod);
	return 0;
}

D. 无双挑战

基本上是点分治板子了

发现 \(dis\) 可加,于是

用树状数组维护一下后缀和即可

题解做法也容易,放在下面

image

code
#include<bits/stdc++.h>
using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pii;

int read(){
	int x = 0; char c = getchar();
	while(!isdigit(c))c = getchar();
	do{x = x * 10 + (c ^ 48); c = getchar();}while(isdigit(c));
	return x;
}

const int maxn = 805005;
const int mod = 998244353;
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 n, m, a[maxn];
vector<int>g[maxn];
int si[maxn], mx[maxn];
bool del[maxn];
void dfs(int x, int fa){
	si[x] = 1; mx[x] = 0;
	for(int v : g[x])if(v != fa && !del[v]){
		dfs(v, x); si[x] += si[v]; mx[x] = max(mx[x], si[v]);
	}
}
int root, S;
void find(int x, int fa){
	mx[x] = max(mx[x], S - si[x]);
	if(mx[x] < mx[root])root = x;
	for(int v : g[x])if(v != fa && !del[v])find(v, x);
}
void Add(int &x, int y){x += y; if(x >= mod) x -= mod;}
struct BIT{
	int t[maxn];
	int lowbit(int x){return x & -x;}
	void add(int x, int val){
		x = m - x + 1;
		while(x <= m){
			Add(t[x], val);
			x += lowbit(x);
		}
	}
	int query(int x){
		int ans = 0; x = m - x + 1;
		while(x){
			Add(ans, t[x]);
			x -= lowbit(x);
		}
		return ans;
	}
}T, t;
vector<int> vec, sub;
int dis[maxn];
int ans;
void link(int x, int fa){
	for(int v : g[x])if(!del[v] && v != fa){
		vec.push_back(v);
		sub.push_back(v);
		dis[v] = dis[x] + 1;
		link(v, x);	
	}
}
void calc(int root){
	dis[root] = 0;
	for(int v : g[root])if(!del[v]){
		dis[v] = 1; vec.push_back(v); sub.push_back(v); link(v, root);
		for(int x : sub)T.add(a[x], dis[x]), t.add(a[x], 1);
		for(int x : sub)Add(ans, mod - 1ll * (T.query(a[x] + 1) + 1ll * t.query(a[x] + 1) * dis[x]) % mod * (m - a[x]) % mod);
		for(int x : sub) T.add(a[x], mod - dis[x]), t.add(a[x], -1);
		sub.clear();
	}
	t.add(a[root], 1); for(int x : vec)T.add(a[x], dis[x]), t.add(a[x], 1);
	Add(ans, 1ll * T.query(a[root] + 1) * (m - a[root]) % mod);
	for(int x : vec)Add(ans, 1ll * (T.query(a[x] + 1) + 1ll * t.query(a[x] + 1) * dis[x]) % mod * (m - a[x]) % mod);
	t.add(a[root], -1); for(int x : vec) T.add(a[x], mod - dis[x]), t.add(a[x], -1);
	vec.clear();
}
void sol(int x){
	dfs(x, 0); S = si[x]; 
	root = 0;
	find(x, 0);
	x = root; calc(x);
	del[x] = true;
	for(int v : g[x])if(!del[v])sol(v);
}
int main(){
	freopen("challenge.in","r",stdin);
	freopen("challenge.out","w",stdout);
	n = read(), m = read();
	for(int i = 1; i <= n; ++i)a[i] = read();
	for(int i = 1; i < n; ++i){
		int u = read(), v = read();
		g[u].push_back(v); g[v].push_back(u);
	}
	si[0] = mx[0] = mod;
	sol(1);
	ans = 1ll * ans * qpow(1ll  * n * (n - 1) % mod, mod - 2) % mod;
	printf("%d\n",ans);
	return 0;
}

posted @ 2022-11-21 17:46  Chen_jr  阅读(17)  评论(0编辑  收藏  举报