Topcoder SRM 806 Div1 题解
Topcoder SRM 806 Div1 题解
比赛的时候做了300 和 500的,排名20左右。
300
大概就是将所有\((x,y)\)的东西放到\((k,x)\)。
每一个点连到它的目标位置。
答案即为\(N^2-N+tot\),\(tot\) 是环个数。
可以发现这张图存在欧拉回路,直接dfs即可。
/*
{
######################
# Author #
# Gary #
# 2021 #
######################
*/
#include<bits/stdc++.h>
#define rb(a,b,c) for(int a=b;a<=c;++a)
#define rl(a,b,c) for(int a=b;a>=c;--a)
#define LL long long
#define IT iterator
#define PB push_back
#define II(a,b) make_pair(a,b)
#define FIR first
#define SEC second
#define FREO freopen("check.out","w",stdout)
#define rep(a,b) for(int a=0;a<b;++a)
#define SRAND mt19937 rng(chrono::steady_clock::now().time_since_epoch().count())
#define random(a) rng()%a
#define ALL(a) a.begin(),a.end()
#define POB pop_back
#define ff fflush(stdout)
#define fastio ios::sync_with_stdio(false)
#define check_min(a,b) a=min(a,b)
#define check_max(a,b) a=max(a,b)
using namespace std;
//inline int read(){
// int x=0;
// char ch=getchar();
// while(ch<'0'||ch>'9'){
// ch=getchar();
// }
// while(ch>='0'&&ch<='9'){
// x=(x<<1)+(x<<3)+(ch^48);
// ch=getchar();
// }
// return x;
//}
const int INF=0x3f3f3f3f;
typedef pair<int,int> mp;
/*}
*/
const int MAXN=40;
vector<int> g[MAXN];
vector<int> ans;
map<mp,int> era;
int n;
void dfs(int now){
for(auto it:g[now]){
if(era[II(now,it)]){
continue;
}
era[II(now,it)]=1;
dfs(it);
ans.PB(it*n+now);
}
}
class TransposeColors{
public:
vector <int> move(int N){
n=N;
if(N==1){
return vector<int> (0);
}
rep(i,N)
rep(j,N) if(i!=j) g[i].PB(j);
dfs(0);
ans.PB(N*N);
return ans;
}
}solver;
500
这题比较套路,处理出\(KMP\)直接dp。
dp的first为最大值,dp的second为方案数。
/*
{
######################
# Author #
# Gary #
# 2021 #
######################
*/
#include<bits/stdc++.h>
#define rb(a,b,c) for(int a=b;a<=c;++a)
#define rl(a,b,c) for(int a=b;a>=c;--a)
#define LL long long
#define IT iterator
#define PB push_back
#define II(a,b) make_pair(a,b)
#define FIR first
#define SEC second
#define FREO freopen("check.out","w",stdout)
#define rep(a,b) for(int a=0;a<b;++a)
#define SRAND mt19937 rng(chrono::steady_clock::now().time_since_epoch().count())
#define random(a) rng()%a
#define ALL(a) a.begin(),a.end()
#define POB pop_back
#define ff fflush(stdout)
#define fastio ios::sync_with_stdio(false)
#define check_min(a,b) a=min(a,b)
#define check_max(a,b) a=max(a,b)
using namespace std;
//inline int read(){
// int x=0;
// char ch=getchar();
// while(ch<'0'||ch>'9'){
// ch=getchar();
// }
// while(ch>='0'&&ch<='9'){
// x=(x<<1)+(x<<3)+(ch^48);
// ch=getchar();
// }
// return x;
//}
const int INF=0x3f3f3f3f;
typedef pair<int,int> mp;
/*}
*/
int fail[101],to[101][26];
mp dp[1004][101];
const int MOD=1e9+7;
mp merge(mp A,mp B){
if(A.FIR!=B.FIR) return max(A,B);
return II(A.FIR,(A.SEC+B.SEC)%MOD);
}
class MostSubstrings{
public:
int count(string s, int l){
int len=s.length();
fail[0]=0;
fail[1]=0;
rb(i,2,len){
fail[i]=fail[i-1];
while(s[i-1]!=s[fail[i]]){
if(fail[i]==0) break;
fail[i]=fail[fail[i]];
}
if(s[i-1]==s[fail[i]]){
fail[i]++;
}
}
rb(i,0,len-1){
rep(c,26){
int now=i;
while(s[now]-'a'!=c){
if(now==0) break;
now=fail[now];
}
if(s[now]-'a'!=c){
to[i][c]=0;
}
else{
to[i][c]=now+1;
}
}
}
rb(i,0,l)
rb(j,0,len) dp[i][j]=II(0,0);
dp[0][0]=II(0,1);
rb(i,0,l-1){
rb(j,0,len-1){
if(dp[i][j].SEC||dp[i][j].FIR);
else continue;
rep(c,26){
int nex=to[j][c];
if(nex==len){
dp[i+1][fail[len]]=merge(dp[i+1][fail[len]],II(dp[i][j].FIR+1,dp[i][j].SEC));
}
else{
dp[i+1][nex]=merge(dp[i+1][nex],dp[i][j]);
}
}
}
}
mp ans=II(0,0);
rb(j,0,len-1) ans=merge(ans,dp[l][j]);
return ans.SEC;
}
}solver;
//int main(){
// cout<<solver.count("decode",
//11)<<endl;
// return 0;
//}
1000
结论比较神奇:
alice输当且仅当\(a_0=a_1=a_2\and a_4=a_5=a_6\and a_0\text{xor}a_3\text{xor}a_4=0\)
知道这个直接暴力即可。
证明:
首先若不满足条件则一定存在操作到达满足上面条件的操作。
若满足一定达到不满足的局面。
(感觉没证明。。。)
/*
{
######################
# Author #
# Gary #
# 2021 #
######################
*/
#include<bits/stdc++.h>
#define rb(a,b,c) for(int a=b;a<=c;++a)
#define rl(a,b,c) for(int a=b;a>=c;--a)
#define LL long long
#define IT iterator
#define PB push_back
#define II(a,b) make_pair(a,b)
#define FIR first
#define SEC second
#define FREO freopen("check.out","w",stdout)
#define rep(a,b) for(int a=0;a<b;++a)
#define SRAND mt19937 rng(chrono::steady_clock::now().time_since_epoch().count())
#define random(a) rng()%a
#define ALL(a) a.begin(),a.end()
#define POB pop_back
#define ff fflush(stdout)
#define fastio ios::sync_with_stdio(false)
#define check_min(a,b) a=min(a,b)
#define check_max(a,b) a=max(a,b)
using namespace std;
//inline int read(){
// int x=0;
// char ch=getchar();
// while(ch<'0'||ch>'9'){
// ch=getchar();
// }
// while(ch>='0'&&ch<='9'){
// x=(x<<1)+(x<<3)+(ch^48);
// ch=getchar();
// }
// return x;
//}
const int INF=0x3f3f3f3f;
typedef pair<int,int> mp;
/*}
*/
int fail[101],to[101][26];
mp dp[1004][101];
const int MOD=1e9+7;
mp merge(mp A,mp B){
if(A.FIR!=B.FIR) return max(A,B);
return II(A.FIR,(A.SEC+B.SEC)%MOD);
}
class MostSubstrings{
public:
int count(string s, int l){
int len=s.length();
fail[0]=0;
fail[1]=0;
rb(i,2,len){
fail[i]=fail[i-1];
while(s[i-1]!=s[fail[i]]){
if(fail[i]==0) break;
fail[i]=fail[fail[i]];
}
if(s[i-1]==s[fail[i]]){
fail[i]++;
}
}
rb(i,0,len-1){
rep(c,26){
int now=i;
while(s[now]-'a'!=c){
if(now==0) break;
now=fail[now];
}
if(s[now]-'a'!=c){
to[i][c]=0;
}
else{
to[i][c]=now+1;
}
}
}
rb(i,0,l)
rb(j,0,len) dp[i][j]=II(0,0);
dp[0][0]=II(0,1);
rb(i,0,l-1){
rb(j,0,len-1){
if(dp[i][j].SEC||dp[i][j].FIR);
else continue;
rep(c,26){
int nex=to[j][c];
if(nex==len){
dp[i+1][fail[len]]=merge(dp[i+1][fail[len]],II(dp[i][j].FIR+1,dp[i][j].SEC));
}
else{
dp[i+1][nex]=merge(dp[i+1][nex],dp[i][j]);
}
}
}
}
mp ans=II(0,0);
rb(j,0,len-1) ans=merge(ans,dp[l][j]);
return ans.SEC;
}
}solver;
//int main(){
// cout<<solver.count("decode",
//11)<<endl;
// return 0;
//}