比赛链接:https://atcoder.jp/contests/abc268/tasks
题解:
C
对于每个盘子统计一下转那几次(3 种情况)能够满足条件
// by SkyRainWind
#include <bits/stdc++.h>
#define mpr make_pair
#define debug() cerr<<"Yoshino\n"
#define pii pair<int,int>
#define pb push_back
using namespace std;
typedef long long ll;
typedef long long LL;
const int inf = 1e9, INF = 0x3f3f3f3f, maxn = 2e5+5;
int n,a[maxn],cnt[maxn];
signed main(){
scanf("%d",&n);
for(int i=0;i<n;i++)scanf("%d",&a[i]);
for(int i=0;i<n;i++){
int now = (a[i]-i+n)%n;
++ cnt[now%n];
++ cnt[(now+1)%n];
++ cnt[(now+n-1)%n];
}
int ans = 0;
for(int i=0;i<n;i++)
ans = max(ans, cnt[i]);
cout << ans << '\n';
return 0;
}
D
\(O(n!)\) 爆搜一下,注意每次下划线的个数和之后单词的个数有关,用 map 判重即可
// by SkyRainWind
#include <bits/stdc++.h>
#define mpr make_pair
#define debug() cerr<<"Yoshino\n"
#define pii pair<int,int>
#define pb push_back
using namespace std;
typedef long long ll;
typedef long long LL;
const int inf = 1e9, INF = 0x3f3f3f3f;
int n,m;
set<string>S;
string s[12];
int vis[12];
void dfs(int x,int rem,string now=""){
if(x == n+1){
if(now.size()<3||now.size()>16)return ;
if(S.count(now))return ;
cout << now << '\n';
exit(0);
}
for(int i=1;i<=n;i++)if(!vis[i]){
vis[i] = 1;
string nn = now+s[i];
if(x==n)dfs(x+1,rem,nn);
else{
for(int un=1;un<=rem;un++)if(un+n-x-1<=rem){
nn = nn + '_';
dfs(x+1,rem-un,nn);
}
}
vis[i] = 0;
}
}
signed main(){
scanf("%d%d",&n,&m);
int sz = 0;
for(int i=1;i<=n;i++){
cin >> s[i];
sz += s[i].size();
}
for(int i=0;i<m;i++){
string t;
cin >>t;
S.insert(t);
}
dfs(1,16-sz,"");
puts("-1");
return 0;
}
E
坑了
F
贪心的交换法,比 E 简单
// by SkyRainWind
#include <bits/stdc++.h>
#define mpr make_pair
#define debug() cerr<<"Yoshino\n"
#define pii pair<int,int>
#define pb push_back
using namespace std;
typedef long long ll;
typedef long long LL;
const int inf = 1e9, INF = 0x3f3f3f3f, maxn=2e5+5;
int n;
string s[maxn];
int sum[maxn],sum2[maxn],id[maxn];
signed main(){
cin.tie(0);ios::sync_with_stdio(false);
cin>>n;
for(int i=1;i<=n;i++){
id[i] = i;
cin>>s[i];
for(int j=0;j<s[i].size();j++){
if(s[i][j]=='X')++sum[i];
else sum2[i]+=s[i][j]-'0';
}
}
sort(id+1,id+n+1,[&](int x,int y){
return 1ll*sum[x]*sum2[y]>1ll*sum[y]*sum2[x];
});
int cx = 0;
ll ans=0;
for(int i=1;i<=n;i++){
string nt = s[id[i]];
for(int j=0;j<nt.size();j++){
if(nt[j] == 'X')++cx;
else{
ans += 1ll*cx*(nt[j]-'0');
}
}
}
cout << ans << '\n';
return 0;
}
G
“脑筋急转弯”
首先,\(E(rank_i)=1+E(rank_j<rank_i)=1+\sum_jPr(rank_j<rank_i)\)
考虑 \(i,j\) 的关系:如果 \(j\) 是 \(i\) 的前缀,显然 \(Pr=0\)
如果 \(i\) 是 \(j\) 的前缀,显然 \(Pr=1\)
否则,\(Pr=1/2\),因为考虑第一个 \(i,j\) 不同的位置,显然大于和小于的方案数是对称相等的,因此为 \(1/2\)
写个 trie 判一下前缀关系即可
// by SkyRainWind
#include <bits/stdc++.h>
#define mpr make_pair
#define debug() cerr<<"Yoshino\n"
#define pii pair<int,int>
#define pb push_back
using namespace std;
typedef long long ll;
typedef long long LL;
const int inf = 1e9, INF = 0x3f3f3f3f, maxn = 5e5+5, mod = 998244353;
const int inv2 = (mod+1)/2;
int n;
char s[maxn];
struct trie{
int tr[maxn][27], cnt = 0, pos[maxn*26], sz[maxn*26];
int mp[maxn * 26];
void insert(char *s,int id){
int n=strlen(s+1);
int p = 0;
for(int i=1;i<=n;i++){
int t = s[i] - 'a';
if(!tr[p][t]){
tr[p][t] = ++cnt;
}
p = tr[p][t];
}
++ pos[p];
mp[p] = id;
}
int ans[maxn];
void dfs(int x,int pref=0,int id=0){
// printf("%d %d %d\n",x,pref,id);
int p = x;
sz[p] = pos[p];
for(int i=0;i<26;i++)if(tr[p][i]){
dfs(tr[p][i], pref+pos[p], mp[tr[p][i]]?mp[tr[p][i]]:0);
sz[p] += sz[tr[p][i]];
}
// printf("? %d %d %d %d %d\n",p,id,sz[p],(n-pref-sz[p]),pref);
if(id)(ans[id] = 1ll*(n-pref-sz[p])*inv2%mod + (pref)%mod + 1) %= mod;
}
}tr;
signed main(){
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%s",s +1);
tr.insert(s, i);
}
tr.dfs(0);
for(int i=1;i<=n;i++)printf("%d\n",tr.ans[i]);
return 0;
}
Ex
建出 AC 自动机之后贪心即可,如果当前位能匹配上而且是末尾,就改成 *
// by SkyRainWind
#include <bits/stdc++.h>
#define mpr make_pair
#define debug() cerr<<"Yoshino\n"
#define pii pair<int,int>
#define pb push_back
using namespace std;
typedef long long ll;
typedef long long LL;
const int inf = 1e9, INF = 0x3f3f3f3f, maxn=1e6+5;
struct AC{
int lst[maxn];
int tr[maxn][27],cnt;
int val[maxn]; // 多少个以 i 结点结尾的单词
int fail[maxn];
AC(){cnt=0;memset(val,0,sizeof val);}
void insert(char *s){
int p=0;
int ns = strlen(s + 1);
for(int i=1;i<=ns;i++){
int k = s[i] - 'a';
if(!tr[p][k])tr[p][k] = ++ cnt;
p = tr[p][k];
}
++ val[p];
}
void build(){
queue<int>Q;
Q.push(0);
while(!Q.empty()){
int u = Q.front();Q.pop();
for(int i=0;i<26;i++)
if(tr[u][i]){
fail[tr[u][i]] = u ? tr[fail[u]][i] : 0;
if(val[fail[tr[u][i]]])lst[tr[u][i]] = fail[tr[u][i]];
else lst[tr[u][i]] = lst[fail[tr[u][i]]];
Q.push(tr[u][i]);
}else tr[u][i] = tr[fail[u]][i];
}
}
void query(char *t){
int p=0, res=0;
int nt = strlen(t + 1);
for(int i=1;i<=nt;i++){
p = tr[p][t[i] - 'a'];
int fg = 0;
if(val[p]){
fg = 1;
}
int v = lst[p];
while(v){ // 沿失配边跳,加上abc bc c这种的匹配
if(val[v]){
fg = 1;
}
v = lst[v];
}
if(fg){
++ res;
p = 0;
}
}
printf("%d\n",res);
}
}ac;
char s[maxn],t[maxn];
int n;
signed main(){
scanf("%s",t+1);
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%s",s +1);
ac.insert(s);
}
ac.build();
ac.query(t);
return 0;
}
标签:typedef,const,int,题解,long,maxn,ABC268,define
From: https://www.cnblogs.com/SkyRainWind/p/17113576.html