这套题的思维量比较少,但是有些题很毒瘤 Orz。
https://codeforces.com/gym/100299
题目按照我过题顺序排的:
L
模拟。
#include<bits/stdc++.h>
using namespace std;
#define debug(x) cerr << #x << ": " << (x) << endl
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define dwn(i,a,b) for(int i=(a);i>=(b);i--)
using pii = pair<int, int>;
using ll = long long;
inline void read(int &x){
int s=0; x=1;
char ch=getchar();
while(ch<'0' || ch>'9') {if(ch=='-')x=-1;ch=getchar();}
while(ch>='0' && ch<='9') s=(s<<3)+(s<<1)+ch-'0',ch=getchar();
x*=s;
}
int main(){
int T; cin>>T;
while(T--){
int n; cin>>n;
cout<<(1<<n)-1<<endl;
}
return 0;
}
B
模拟,字符串处理。
#include<bits/stdc++.h>
using namespace std;
#define debug(x) cerr << #x << ": " << (x) << endl
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define dwn(i,a,b) for(int i=(a);i>=(b);i--)
using pii = pair<int, int>;
using ll = long long;
inline void read(int &x){
int s=0; x=1;
char ch=getchar();
while(ch<'0' || ch>'9') {if(ch=='-')x=-1;ch=getchar();}
while(ch>='0' && ch<='9') s=(s<<3)+(s<<1)+ch-'0',ch=getchar();
x*=s;
}
string s[110], tmp[4];
map<string, bool> vis;
int main(){
int T; cin>>T; getchar();
while(T--){
string t;
int tot=0;
while(getline(cin, t)){
if(t=="what does the fox say?") break;
s[++tot]=t;
}
vis.clear();
rep(i,2,tot){
int cur=0;
stringstream ssin(s[i]);
while(ssin>>t) tmp[++cur]=t;
vis[tmp[3]]=true;
}
stringstream ssin(s[1]);
while(ssin>>t) if(!vis[t]) cout<<t<<' ';
cout<<endl;
}
return 0;
}
F
搜索。
注意题意说的是:一步棋中用一个棋子连续吃掉几个棋子。通过向前或向后的跳跃来吃子也是合法的。
所以我们可以对于棋盘上每一个白棋进行搜索,并找出它们在所有的决策中能够吃掉的最多黑棋,那么这个过程搜索 + 回溯就可以解决了。
#include<bits/stdc++.h>
using namespace std;
#define debug(x) cerr << #x << ": " << (x) << endl
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define dwn(i,a,b) for(int i=(a);i>=(b);i--)
using pii = pair<int, int>;
using ll = long long;
inline void read(int &x){
int s=0; x=1;
char ch=getchar();
while(ch<'0' || ch>'9') {if(ch=='-')x=-1;ch=getchar();}
while(ch>='0' && ch<='9') s=(s<<3)+(s<<1)+ch-'0',ch=getchar();
x*=s;
}
const int n=10, N=15;
char g[N][N];
int dfs(int x, int y){
int res=0;
for(int i=-1; i<=1; i+=2) for(int j=-1; j<=1; j+=2){
int kx=i+x, ky=j+y;
if(kx<1 || kx>n || ky<1 || ky>n) continue;
if(g[kx][ky]!='B') continue;
int X=x+2*i, Y=y+2*j;
if(X<1 || X>n || Y<1 || Y>n) continue;
if(g[X][Y]!='#') continue;
// ok
g[kx][ky]='#';
res=max(res, dfs(X, Y)+1);
g[kx][ky]='B';
}
return res;
}
int main(){
int T; cin>>T;
while(T--){
rep(i,1,n) rep(j,1,n) cin>>g[i][j];
int res=0;
rep(i,1,n) rep(j,1,n) if(g[i][j]=='W'){
g[i][j]='#';
res=max(res, dfs(i, j));
g[i][j]='W';
}
cout<<res<<endl;
}
return 0;
}
I
#include<bits/stdc++.h>
using namespace std;
#define debug(x) cerr << #x << ": " << (x) << endl
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define dwn(i,a,b) for(int i=(a);i>=(b);i--)
using pii = pair<int, int>;
using ll = long long;
inline void read(int &x){
int s=0; x=1;
char ch=getchar();
while(ch<'0' || ch>'9') {if(ch=='-')x=-1;ch=getchar();}
while(ch>='0' && ch<='9') s=(s<<3)+(s<<1)+ch-'0',ch=getchar();
x*=s;
}
const int N=10010;
int w[N], n;
struct Msg{
int x, y;
}res[N*55];
int tot;
int main(){
int T; cin>>T;
while(T--){
cin>>n;
rep(i,1,n) read(w[i]);
tot=0;
rep(i,1,n){
int p;
rep(j,i,n) if(w[j]==i){
p=j;
break;
}
if(p==i) continue;
while(i!=p){
if(p-i&1){
res[++tot]={i, p};
int mid=p+i>>1;
rep(j,i,mid) swap(w[j], w[j+(p-i+1)/2]);
p=mid;
}
else{
res[++tot]={i+1, p};
int mid=p+i+1>>1;
rep(j,i+1,mid) swap(w[j], w[j+(p-i)/2]);
p=mid;
}
}
}
cout<<tot<<endl;
rep(i,1,tot) printf("%d %d
", res[i].x, res[i].y);
}
return 0;
}
C
注意到当固定右端点 (i) 时,其左边最多有 (log~i) 段不同的 (gcd) 值,而且这个值向左递减,所以我们可以用二分来向左跳并更新答案。
至于区间 (gcd) 值用 ST 表维护就行了。
#include<bits/stdc++.h>
using namespace std;
#define debug(x) cerr << #x << ": " << (x) << endl
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define dwn(i,a,b) for(int i=(a);i>=(b);i--)
using pii = pair<int, int>;
using ll = long long;
#define int long long
inline void read(int &x){
int s=0; x=1;
char ch=getchar();
while(ch<'0' || ch>'9') {if(ch=='-')x=-1;ch=getchar();}
while(ch>='0' && ch<='9') s=(s<<3)+(s<<1)+ch-'0',ch=getchar();
x*=s;
}
const int N=1e5+5;
int n, w[N];
int st[N][25], Log[N];
int gcd(int a, int b){
return b? gcd(b, a%b): a;
}
void build(){
rep(i,2,N-1) Log[i]=Log[i/2]+1;
rep(j,0,20) for(int i=1; i+(1<<j)-1<=n; i++){
if(!j) st[i][0]=w[i];
else st[i][j]=gcd(st[i][j-1], st[i+(1<<j-1)][j-1]);
}
}
int query(int l, int r){
int k=Log[r-l+1];
return gcd(st[l][k], st[r-(1<<k)+1][k]);
}
int find(int val, int l, int r){
int R=r;
while(l<r){
int mid=l+r>>1;
if(query(mid, R)>=val) r=mid;
else l=mid+1;
}
return l;
}
signed main(){
int T; cin>>T;
while(T--){
cin>>n;
rep(i,1,n) read(w[i]);
build();
int res=0;
rep(i,1,n){
int r=i;
while(r){
int val=query(r, i);
int l=find(val, 1, i);
res=max(res, (i-l+1)*val);
r=l-1;
}
}
cout<<res<<endl;
}
return 0;
}
K
我将这题写成大模拟了(悲。
思路很简单:
- 将所给的关系建成图
- 若图上存在环,直接用环构造即可。
- 不存在环则在 DAG 上找到最长链(长度记为 (sz)),构造出的方阵长为 ((sz+1)/2)。
#include<bits/stdc++.h>
using namespace std;
#define debug(x) cerr << #x << ": " << (x) << endl
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define dwn(i,a,b) for(int i=(a);i>=(b);i--)
using pii = pair<int, int>;
using ll = long long;
inline void read(int &x){
int s=0; x=1;
char ch=getchar();
while(ch<'0' || ch>'9') {if(ch=='-')x=-1;ch=getchar();}
while(ch>='0' && ch<='9') s=(s<<3)+(s<<1)+ch-'0',ch=getchar();
x*=s;
}
const int n=26, N=35;
int g[N][N];
int m;
int get(char t){
return t-'a'+1;
}
char rget(int t){
return t-1+'a';
}
int res[N][N];
int deg[N];
int q[N];
int tt, hh;
int f[N], pre[N];
vector<int> lk; // link
bool topsort(){
tt=-1, hh=0;
int cnt=0;
rep(i,1,n) if(!deg[i]) q[++tt]=i, cnt++, f[i]=1;
while(tt>=hh){
int u=q[hh++];
rep(v,1,n) if(v!=u && g[u][v]){
if(--deg[v]==0){
q[++tt]=v, cnt++;
if(f[v]<f[u]+1){
f[v]=f[u]+1;
pre[v]=u;
}
}
}
}
return cnt==n;
}
bool vis[N];
int stk[N], top;
bool gotLoop;
void dfs(int u, int root){
if(gotLoop) return;
if(vis[u]){
if(root==u){
gotLoop=true;
}
return;
}
stk[++top]=u;
vis[u]=true;
rep(v,1,n) if(v!=u && g[u][v]){
dfs(v, root);
if(gotLoop) return;
}
top--;
vis[u]=false;
}
void check(int sz){
bool ok=true;
rep(i,1,sz) rep(j,1,sz-1) if(!g[res[i][j]][res[i][j+1]]) ok=false;
rep(i,1,sz) rep(j,1,sz-1) if(!g[res[j][i]][res[j+1][i]]) ok=false;
if(ok) cerr<<"AC"<<endl;
else cerr<<"WA"<<endl;
}
int main(){
int T; cin>>T;
while(T--){
cin>>m;
rep(i,1,n) rep(j,1,n) g[i][j]=1;
while(m--){
string t; cin>>t;
int u=get(t[0]), v=get(t[1]);
g[u][v]=0;
}
bool ed=false; int rec; // self loop
rep(i,1,n) if(g[i][i]) ed=true, rec=i;
if(ed){
rep(i,1,20){
rep(j,1,20) cout<<rget(rec);
cout<<endl;
}
continue;
}
rep(i,1,n) deg[i]=pre[i]=f[i]=vis[i]=0;
rep(i,1,n) rep(j,1,n) if(g[i][j]) deg[j]++;
if(topsort()){
int u, val=0;
rep(i,1,n) if(f[i]>val) val=f[i], u=i;
lk.clear();
while(u){
lk.push_back(u);
u=pre[u];
}
reverse(begin(lk), end(lk));
int sz=(int)lk.size()+1>>1;
rep(i,1,sz) rep(j,1,sz) res[i][j]=lk[i+j-2];
rep(i,1,sz){
rep(j,1,sz) cout<<rget(res[i][j]);
cout<<endl;
}
// check(sz);
}
else{
gotLoop=false;
rep(i,1,n){
if(gotLoop) break;
rep(j,1,n) vis[j]=false;
top=0;
dfs(i, i);
}
rep(i,1,20) rep(j,1,20) res[i][j]=stk[(i+j)%top+1];
rep(i,1,20){
rep(j,1,20) cout<<rget(res[i][j]);
cout<<endl;
}
// check(20);
}
}
return 0;
}