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
题面链接
设
显然,若起点 \(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

浙公网安备 33010602011771号