JKQ 杯 2026/05/11(Div.3 自测)题解

A

题面链接
不会做的看了也没用。

A - code
#include <bits/stdc++.h>
using namespace std;
const int N = 1e6 + 5;
int n;
char s[N];
int alac (char c){
	if (c >= '0' && c <= '9') return c - '0';
	else if (c == 'a') return 10;
	else if (c == 'b') return 11;
	else if (c == 'c') return 12;
	else if (c == 'd') return 13;
	else if (c == 'e') return 14;
	return 15;
}
char clac (int c){
	if (c >= 0 && c <= 9) return c + '0';
	else if (c == 10) return 'a';
	else if (c == 11) return 'b';
	else if (c == 12) return 'c';
	else if (c == 13) return 'd';
	else if (c == 14) return 'e';
	return 'f';
}
int main() {
	scanf ("%d", &n);
	scanf ("%s", s + 1);
	for (int i = 1; i <= n; i++){
        putchar (clac (15 - alac (s[i])));
    }
    return 0;
}
B

题面链接
明显不能有 \(2\) 个以上 1 存在于互相对称的两列,所以考虑分类一下情况。

  • \(2\) 个 1 在同一列,则两行操作需不同。
  • \(2\) 个 1 不在同一列,则两行操作需相同。
  • 小于 \(2\) 个 1,不影响。
    判断一下每个连通块合不合法,若有 \(cnt\) 个连通块,合法答案就是 \(2^{cnt}\),不合法仍然为 \(0\)
B - code
#include <bits/stdc++.h> 
using namespace std;
const int N = 1e6 + 5;
int t,n,m;
int p2[N],vis[N],mod = 998244353;
bool flag;
string a;
struct node {int u,w;};
vector <int> s[N];
vector <node> E[N];
void dfs (int u){ 
    if (flag) return ;
	for (auto [v, w] : E[u]){
    	if (vis[v] == 0){
        	vis[v] = vis[u] ^ w;
         	dfs (v); 
    	} 
    	else if ((vis[u] ^ vis[v]) != w){ 
        	flag = 1;
			return ; 
    	} 
	} 
} 
void solve (){ 
    cin >> n >> m; 
	for (int i = 1; i <= n; i++) vis[i] = 0; 
	for (int i = 1; i <= n; i++) E[i].clear(); 
	for (int i = 1; i <= m; i++) s[i].clear(); 
	for (int i = 1; i <= n; i++){ 
	    cin >> a; 
		a = ' ' + a; 
		for (int j = 1; j <= m; j++){ 
		    if (a[j] == '1'){ 
			    s[j].push_back (i); 
			} 
		} 
	} 
	for (int i = 1; i <= (m + 1) / 2; i++){ 
	    if (s[i].size() + s[m - i + 1].size() > 2){ 
		    cout << 0 << '\n'; return ; 
		} 
		int pos = -1;
		if (s[i].size() == 2) pos = i; 
		else if (s[m - i + 1].size() == 2) pos = m - i + 1; 
		else if (s[i].size() == 1 && s[m - i + 1].size() == 1){ 
		    E[s[i][0]].push_back ({s[m - i + 1][0], 0}); 
			E[s[m - i + 1][0]].push_back ({s[i][0], 0}); 
		} 
		if (pos != -1){ 
		    E[s[pos][0]].push_back ({s[pos][1], 1}); 
			E[s[pos][1]].push_back ({s[pos][0], 1}); 
		} 
	} 
	flag = 0; 
	int cnt = 0; 
	for (int i = 1; i <= n; i++){ 
	    if (flag) break; 
		if (vis[i]) continue; 
		++cnt; 
		vis[i] = 2; 
		dfs (i); 
	} 
	cout << (flag ? 0 : p2[cnt]) <<'\n'; 
} 
int main(){
    ios::sync_with_stdio(0); 
	cin.tie(0); cout.tie(0); 
	p2[0] = 1; 
	for (int i = 1; i < N; i++) p2[i] = (p2[i - 1] << 1) % mod; 
	cin >> t; 
	while (t--) solve (); 
	return 0; 
}
C

题面链接
模拟就行。

C - code by dengshenghao.
#include<bits/stdc++.h>
using namespace std;
const int N=1500+7;
string s;
int ans[15],a[15][5];
string b[15];
map<string,int>mp;
string c[3]={"seer","commoner","werewolf"};
vector<pair<int,int>>E[15];
bool check (){
	for(int i=1;i<=12;i++){
			if(ans[i]==1){
				if(a[i][2]||a[i][3]) return 0;
			}
			if(ans[i]==3){
				if(a[i][3]) return 0;
			}
	}
	for(int i=1;i<=12;i++){
		if(ans[i]==1){
			for(auto now:E[i]){
				int u=now.first,w=now.second;
				if(ans[u]!=w) return 0;
			}
    	}
    	if(ans[i]==3){
	    	for(auto now:E[i]){
		    	int u=now.first,w=now.second;
		    	if(ans[u]==w) return 0;
				}
			}
	}
	return 1;
}
int main(){
	int cnt=0;
    while(getline(cin,s)){
        if (!s.empty() && s.back() == '\r')
            s.pop_back();
    	string s1,s2,s3,s4;
    	int r=0,r1=0;
    	for(int i=0;i<s.length();i++){
    		if(s[i]==':'){
    			r=i+2;
    			break;
			}
			s1+=s[i];
		}
		if(!mp[s1]){
			mp[s1]=++cnt;
			b[cnt]=s1;
		}
		for(int i=s.length()-1;i>=0;i--){
			if(s[i]==' '){
				r1=i-1;
				break;
			}
			s2+=s[i];
		}
        for(;r1>=0;r1--){
        	if(s[r1]==' '){
        		break;
			}
			s3+=s[r1];
		}
		reverse(s2.begin(),s2.end());
		reverse(s3.begin(),s3.end());
		if(s3=="I'm"){
			if(s2=="commoner.") a[mp[s1]][2]=1;
			if(s2=="seer.") a[mp[s1]][1]=1;
			if(s2=="werewolf.") a[mp[s1]][3]=1;
		}
		else{
			for(int i=r;i<=r1;i++){
				s4+=s[i];
			}
		   	if(!mp[s4]){
		    	mp[s4]=++cnt;
		    	b[cnt]=s4;
	    	}
			if(s2=="commoner.") E[mp[s1]].push_back({mp[s4],2});
			if(s2=="seer.") E[mp[s1]].push_back({mp[s4],1});
			if(s2=="werewolf.") E[mp[s1]].push_back({mp[s4],3});
		}
	}
	for (int i = 1; i < (1 << 12); i++){
		int sum = 0;
		for (int j = 1; j <= 12; j++){
			ans[j] = 2;
			if (i & (1 << (j - 1))){
				sum++; ans[j] = 3;
			}
		}
		if (sum != 5) continue;
		for (int j = 1; j <= 12; j++){
			if (ans[j] == 3) continue;
			ans[j] = 1;
			if (check ()){
				for(int k=1;k<=12;k++){
		        	cout<<b[k]<<':'<<' '<<c[ans[k]-1]<<'\n';
	        	}
				return 0;
			}
            ans[j] = 2;
		}
	}
}
D

题面链接

\[p_i = \sum_{j=1}^i a_j \pmod n \]

显然,若起点 \(s\) 不存在 \(s + p_j \equiv X \pmod n\),则会落到 \((s + p_m) \mod n\)

若存在,假设我们知道最小的 \(k\) 使得 \(Y + p_k - p_j \equiv X \pmod n\),那么 第 \(j\) 步后与第 \(k\) 步后落点是相同的,均为 \(Y\)。那就我们就只需倒序计算,判断会不会再经过点 \(X\),有则落点相同,无则落点为剩余步数走完。

\(g(i)\) 为当前答案的映射,使得 \(i\) 点起始的答案为 \(g[(i + sumstep) \mod n]\)
初始化 \(g(i) = i\),倒序统计当前步数,依次更新 \(g[(X + nowstep) \mod n]\)\(g[(Y + nowstep) \mod n]\)\(nowstep\)\((nowstep + a[j]) \mod n\) 即可。
下图可以辅助理解:

D - code
#include <bits/stdc++.h>
using namespace std;
int N, K, X, Y;
void solve() {
    cin >> N >> K >> X >> Y;
    vector<int> a(K);
    for (int i = 0; i < K; ++i) {
        cin >> a[i];
    }
    vector<int> G(N);
    iota (G.begin(), G.end(), 0);
    int C = 0;
    for (int i = K - 1; i >= 0; --i) {
        int idx = (X + C) % N;
        int val = G[(Y + C) % N];
        G[idx] = val;
        C = (C + a[i]) % N;
    }
    for (int s = 0; s < N; ++s) {
        if (s == X) continue;
        cout << G[(s + C) % N] << ' ';
    }
    cout << '\n';
}
int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int T;
    cin >> T;
    while (T--) solve();
    return 0;
}
E

题面链接
构造题不多解释。

E - code - 1

by dengshenghao

#include<bits/stdc++.h>
using namespace std;
#define int long long
int t,n;
signed main(){
	cin>>t;
	while(t--){
		cin>>n;
		if(n==1){
			cout<<1<<'\n';
			continue;
		}
		if(n%2==0){
			cout<<n<<' ';
			int l=2,r=n/2+1;
			while(l<=n/2&&r<n){
				cout<<l<<' '<<r<<' ';
				l++;
				r++;
			}
			cout<<1<<'\n';
		}
		else{
			cout<<n-1<<' ';
			int l=2,r=(n-1)/2+1;
			while(l<=(n-1)/2&&r<n-1){
				cout<<l<<' '<<r<<' ';
				l++;
				r++;
			}
			cout<<1<<' '<<n<<'\n';
		}
	}
    return 0;
}
E - code - 2

by MARSHALHEREWEARE(pre)

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

int t;
int n;

int main()
{
	cin>>t;
	while(t--){
		cin>>n;
		if(n==1){
			cout<<1<<"\n";
			continue;
		}
		int b1=n/2+1,b2=1;
		cout<<b1<<" "<<b2<<" ";
		for(int i=3;i<=n;i++){
			if(i%2==0)cout<<++b2<<" ";
			else cout<<++b1<<" ";
		}
		cout<<"\n";
	}
	return 0;
}
F

题面链接
dijstra 跑两遍最短路,注意多一维 —— 魔力使用次数。

F - code
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int N = 1500;
int T,n,m,k,x,y,z;
ll ans[N], dis[2][N][N], inf = 1e15;
struct node{
	int u;
    ll w;
    int nz;
	bool operator < (const node &lyh) const{
		return w > lyh.w; 
	}
};
struct node2 {int u; ll w;};
vector <node2> E[N];
void dijstra (int s, int p){
	priority_queue <node> q;
	q.push ({s, dis[p][s][0] = 0, 0});
	while (!q.empty()){
		int u = q.top().u, nz = q.top().nz; q.pop();
		if (nz > 100) continue;
		for (int j = 0; j < E[u].size(); j++){
			int v = E[u][j].u;
			ll w = E[u][j].w;
			if (dis[p][v][nz] > dis[p][u][nz] + w){
				dis[p][v][nz] = dis[p][u][nz] + w;
				q.push ({v, dis[p][v][nz], nz});
			}
			if (nz < k && dis[p][v][nz + 1] > dis[p][u][nz]){
				dis[p][v][nz + 1] = dis[p][u][nz];
				q.push ({v, dis[p][v][nz + 1], nz + 1});
			}
		}
	}
}
void solve (){
	cin >> n >> m >> k;
	for (int i = 1; i <= m; i++){
        int zz,zy;
		cin >> x >> y >> z;
		E[x].push_back ({y, z});
        E[y].push_back ({x, z});
	}
	for (int i = 1; i <= n; i++){
		for (int j = 0; j <= k; j++){
			dis[1][i][j] = dis[0][i][j] = inf;
		}
	}
	dijstra (1, 0);
	dijstra (n, 1);
    for (int i = 0; i <= k; i++) ans[i] = inf;
    for (int i = 1; i <= n; i++){
    	for (int j = 1; j <= k; j++){
    		dis[0][i][j] = min (dis[0][i][j], dis[0][i][j - 1]);
    		dis[1][i][j] = min (dis[1][i][j], dis[1][i][j - 1]);
		}
	}
    for (int i = 1; i <= n; i++){
        for (int j = 0; j <= k; j++){
            if (j > 100) break;
            for (int l = 0; l <= k - j; l++){
            	if (ans[j + l] == 0) break;
            	if (l > 100) break;
                ans[j + l] = min (ans[j + l], dis[0][i][j] + dis[1][i][l]);
            }
        }
    }
    for (int i = 1; i <= k; i++) ans[i] = min (ans[i], ans[i - 1]);
    for (int i = 0; i <= k; i++){
        if (i > 100){
            cout << 0 << ' ';
            continue;
        }
        cout << ans[i] / 2;
        if (ans[i] & 1) cout << ".5";
        cout << ' ';
    }
    cout << '\n';
	for (int i = 1; i <= n; i++) E[i].clear();
}
int main(){
	ios::sync_with_stdio(0);
	cin.tie(0); cout.tie(0); 
	cin >> T;
	while (T--) solve ();
}
G

题面链接
本质是树上染色,最短路径显然是 \(dfs\) 一遍,设 \(dp_u\)\(u\) 为土豆队时的方案数,则答案为 \(dp_1\)。思考如何从子树转移,如果子树的节点个数都是偶数,显然遍历完每个子树的顺序不影响子节点的染色情况,都与父节点不同,所以此时 \(dp_u = \prod dp_v\)。否则若有子树的节点个数是奇数,设奇数有 \(q\) 个,偶数有 \(p\) 个,一个偶数可以放在奇数后,使得颜色不同,贡献 \(2 ^ p\),相邻遍历的奇数子树相互之间显然颜色不同,贡献 \(\tbinom{q}{\lfloor \frac{q} {2} \rfloor}\),所以此时 $$dp_u = 2 ^ p \dbinom{q}{\lfloor \frac{q} {2} \rfloor} \prod dp_v$$

G - code
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int N = 5e5 + 5;
int T,n,x,y;
ll pow2[N],inv[N],iny[N], mod = 998244353;
ll sz[N],f[N];
vector <int> E[N];
ll ksm (ll a, ll b){
	ll res = 1, c = a;
	while (b){
		if (b & 1) res = (res * c) % mod;
		c = (c * c) % mod;
		b >>= 1;
	}
	return res;
}
void intint (){
	pow2[0] = inv[0] = iny[0] = 1;
	for (int i = 1; i < N - 4; i++) inv[i] = (inv[i - 1] * i) % mod;
	for (int i = 1; i < N - 4; i++) iny[i] = ksm (inv[i], mod - 2);
	for (int i = 1; i < N - 4; i++) pow2[i] = (pow2[i - 1] << 1) % mod;
}
ll C (ll a, ll b){
	return (((inv[a] * iny[b]) % mod) * iny[a - b]) % mod;
}
void dfs1 (int u, int fa){
	sz[u] = 1;
	for (auto v : E[u]){
		if (v == fa) continue;
		dfs1 (v, u);
		sz[u] += sz[v];
	}
}
ll dfs2 (int u, int fa){
    f[u] = 1;
	int cnt1 = 0, cnt2 = 0;
	for (auto v : E[u]){
		if (v == fa) continue;
        dfs2 (v, u);
		f[u] = (f[u] * f[v]) % mod;
		if (sz[v] & 1) cnt1++;
		else cnt2++;
	}
	if (cnt1 > 0){
		f[u] = (((C (cnt1, cnt1 / 2) * pow2[cnt2]) % mod) * f[u]) % mod;
	}
    return f[u];
}
void solve (){
	cin >> n;
	for (int i = 1; i <= n; i++) E[i].clear();
	for (int i = 1; i < n; i++){
		cin >> x >> y;
		E[x].push_back (y);
		E[y].push_back (x);
	}
	dfs1 (1, 0);
	cout << dfs2 (1, 0) << '\n';
}
int main(){
	ios::sync_with_stdio(0);
	cin.tie(0); cout.tie(0);
	intint ();
	cin >> T;
	while (T--) solve ();
	return 0;
}
H

题面链接
暂时没有写 qaq

posted @ 2026-05-25 13:45  CGK_by_SA  阅读(19)  评论(0)    收藏  举报