The 2023 ICPC 网络赛第一场 ADI

Nannan Lv5

The 2023 ICPC Asia Regionals Online Contest (1)

A Qualifiers Ranking Rules

思路:按位次为第一关键字,场次为第二关键字排序即可。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
// AC one more times
// nndbk
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod = 1e9 + 7;
const int N = 2e5 + 10;
int n,m;
int main()
{
ios::sync_with_stdio(false); cin.tie(nullptr), cout.tie(nullptr);
cin>>n>>m;
set<string>s;
vector<pair<array<int,2>,string>>v;
int cnt = 0;
for(int i = 1;i <= n;i++)
{
string x;
cin>>x;
if(s.find(x)==s.end())
v.push_back({{++cnt,1},x});
s.insert(x);

}
cnt = 0;
s.clear();
for(int i = 1;i <= m;i++)
{
string x;
cin>>x;
if(s.find(x)==s.end())
v.push_back({{++cnt,2},x});
s.insert(x);

}
sort(v.begin(), v.end());
s.clear();
for(auto [i,x]:v)
{
if(s.find(x)==s.end())
cout<<x<<"\n";
s.insert(x);
}

return 0;
}

D Transitivity

思路:个点构成完全图需要条边。

如果这个连通块不是完全图,那么答案加上(m是当前连通块边数)

如果全都是完全图呢?由于至少连一条边,那么我们考虑选两个点数最少的使得它们成为完全图。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
// AC one more times
// nndbk
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod = 1e9 + 7;
const int N = 2e6 + 10;
ll fa[N],ret[N],d[N],sz[N];
bool vis[N];
int find(int x)
{
if(x==fa[x])return x;
return fa[x] = find(fa[x]);
}
ll fx(ll x)
{
return (x-1)*x/2;
}
vector<pair<int,int>>vec;
int main()
{
ios::sync_with_stdio(false); cin.tie(nullptr), cout.tie(nullptr);
int n,m;
cin>>n>>m;
for(int i = 1;i <= n; i++)
fa[i] = i,sz[i] = 1;
for(int i = 1;i <= m; i++)
{
int u,v;
cin>>u>>v;
d[u]++,d[v]++;
vec.push_back({u,v});
}

for(auto [u,v] : vec)
{
int fu = find(u),fv = find(v);
if(fu != fv)
{
sz[fv] += sz[fu];
d[fv] += d[fu];
fa[fu] = fv;
}
}

bool hav = false;
int cnt = 0;
ll ans = 0;
for(int i = 1;i <= n; i++)
{
int x = find(i);
if(!vis[x])
{
vis[x] = true;
if(fx(sz[x])==d[x]/2)
ret[++cnt] = sz[x];
else{
hav = true;
ans += fx(sz[x])-d[x]/2;
}
}
}

if(hav)
{
cout<<ans<<"\n";
return 0;
}

sort(ret+1,ret+1+cnt);
ll ve = ret[1]+ret[2];
ll ed = fx(ret[1])+fx(ret[2]);
cout<<fx(ve)-ed<<"\n";

return 0;
}

I Pa?sWorD

思路:状压+前缀和优化。

考虑从前往后枚举,

表示当前第位,第位填(0-25 小写,26-51大写,52-61数字,62什么都没有),状态是(二进制表示:小写、大写、数字)。

如果当前位置的话,那么当前位可以是小写,大写或者数字。

由于我们发现只由位转移过来,那么我们考虑用滚动数组。

枚举61种可能(i),然后从前面62种状态(t)和所有k继去继承。

假如第位是选择填上小写字母的话,由于相邻两位不能一样,于是:

1
2
3
4
5
//假设当前位填j,上一位填t
if(j==t)continue;
else{
dp[now][j][k|(1<<2)] += dp[pre][t][k];
}

但是这个思路的复杂度是$O(1000006262*8)T$,

其实我们考虑从上一位转移过来,考虑可转移的情况()中只有当(相邻两位一样了)的情况的不符合条件的。那么这里可以考虑做一个前缀和优化。我们可以把上一位转移过来的所有情况数加和,之后再减去不符合条件的。

还是以当前位是问号,填小写字母为例:

1
2
3
4
5
6
for(int j = 0;j<26;j++)
for(int k = 0; k < (1<<3); k++)
for(int w = 0; w < (1<<3); w++)if((w|(1<<2))==k){
dp[now][j][k] += ((a[w]-dp[pre][j][w])%mod+mod)%mod;
dp[now][j][k] %= mod;
}

以上思路对于这一位填上大写或者数字是同理的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
// AC one more times
// nndbk
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod = 998244353;
const int N = 2e5 + 10;
int n;
string s;
ll dp[2][70][8];
int main()
{
ios::sync_with_stdio(false); cin.tie(nullptr), cout.tie(nullptr);
cin>>n>>s;
s = "?"+s;
//0~25,26~52,52~61,62
for(int i = 1;i <= n; i++)
{
int now = i&1, pre = (i-1)&1;
if(i==1)
dp[pre][62][0] = 1;
for(int j = 0;j <= 62; j++)
for(int k = 0;k < (1<<3); k++)
dp[now][j][k] = 0;
vector<int>a(10);
for(int j = 0;j <= 62; j++)
for(int k = 0; k < (1<<3); k++)
a[k] += dp[pre][j][k],a[k]%=mod;
if(s[i]=='?')
{
for(int j = 0;j < 26; j++)
for(int k = 0;k < (1<<3); k++)
for(int w = 0;w < (1<<3); w++)if((w|(1<<2))==k){
dp[now][j][k] += ((a[w]-dp[pre][j][w])%mod+mod)%mod;
dp[now][j][k] %= mod;
}

for(int j = 26;j < 52; j++)
for(int k = 0;k < (1<<3); k++)
for(int w = 0;w < (1<<3); w++)if((w|(1<<1))==k){
dp[now][j][k] += ((a[w]-dp[pre][j][w]+mod)%mod)%mod;
dp[now][j][k] %= mod;
}
for(int j = 52;j < 62; j++)
for(int k = 0;k < (1<<3); k++)
for(int w = 0;w < (1<<3); w++)if((w|(1<<0))==k){
dp[now][j][k] += ((a[w]-dp[pre][j][w])%mod+mod)%mod;
dp[now][j][k] %= mod;
}
}
else if(s[i]>='a'&&s[i]<='z')
{
int j = s[i]-'a';
for(int k = 0;k < (1<<3); k++)
for(int w = 0;w < (1<<3); w++)if((w|(1<<2))==k){
dp[now][j][k] += ((a[w]-dp[pre][j][w])%mod+mod)%mod;
dp[now][j][k] %= mod;
}
j += 26;
for(int k = 0;k < (1<<3); k++)
for(int w = 0;w < (1<<3); w++)if((w|(1<<1))==k){
dp[now][j][k] += ((a[w]-dp[pre][j][w])%mod+mod)%mod;
dp[now][j][k] %= mod;
}
}
else if(s[i]>='A'&&s[i]<='Z')
{
int j = s[i]-'A'+26;
for(int k = 0;k < (1<<3); k++)
for(int w = 0;w < (1<<3); w++)if((w|(1<<1))==k){
dp[now][j][k] += ((a[w]-dp[pre][j][w])%mod+mod)%mod;
dp[now][j][k] %= mod;
}
}
else
{
int j = s[i]-'0'+52;
for(int k = 0;k < (1<<3); k++)
for(int w = 0;w < (1<<3); w++)if((w|(1<<0))==k){
dp[now][j][k] += ((a[w]-dp[pre][j][w])%mod+mod)%mod;
dp[now][j][k] %= mod;
}
}
}

ll ans = 0;
for(int j = 0;j <= 62; j++)
ans += dp[n&1][j][7],ans%=mod;
cout<<ans%mod<<"\n";
return 0;
}

  • Title: The 2023 ICPC 网络赛第一场 ADI
  • Author: Nannan
  • Created at : 2023-09-18 19:31:00
  • Updated at : 2024-09-30 17:02:09
  • Link: https://redefine.ohevan.com/2023/09/18/The 2023 ICPC Asia Regionals Online Contest (1)/
  • License: This work is licensed under CC BY-NC-SA 4.0.
Comments