T1 Start 10Pts
題面(較長)
大模擬。
點選檢視程式碼
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int inf=INT_MAX;
string nm[10]={"","D","B","A","C","E","PASS","TURN","DOUBLE"};
string nmm[10]={"","C","A","B","D","E","PASS","TURN","DOUBLE"};
struct card{
string name;
int num;
void input(){
string s;
cin>>s;
if(s!="PASS"&&s!="TURN"&&s!="DOUBLE"){
name=s[0];
int x=0;
for(int i=1;i<(int)s.size();i++){
x=(x<<3)+(x<<1)+(s[i]^48);
}
num=x;
}
else name=s,num=0;
}
};
struct player{
string name;
card c[5];
int nxt,pre;
}a[10];
int n,m,k,p,now,minn,miid;
queue<card> q;
card tmp;
bool db;
int playbig(int x,int p){
int maxn=-inf,id=0;
for(int i=1;i<=5;i++){
for(int j=1;j<=3;j++){
tmp=a[x].c[j];
if(tmp.name==nmm[i]){
int to=p;
if(i==1)to*=tmp.num;
else if(i==2)to+=tmp.num;
else if(i==3)to-=tmp.num;
else if(i==4)to>>=1;
else if(i==5)to=tmp.num;
if(to>99)continue;
if(to>maxn){
maxn=to;
id=j;
}
}
}
}
if(id){
tmp=q.front();
q.pop();
cout<<a[x].name<<" used "<<a[x].c[id].name<<a[x].c[id].num<<",now p="<<maxn<<".\n";
a[x].c[id]=tmp;
return maxn;
}
for(int i=6;i<=8;i++){
for(int j=1;j<=3;j++){
tmp=a[x].c[j];
if(tmp.name==nmm[i]){
if(i==6){
card tmpp=q.front();
q.pop();
cout<<a[x].name<<" used "<<a[x].c[j].name<<",now p="<<p<<".\n";
a[x].c[j]=tmpp;
return p+1e6;
}
else if(i==7){
card tmpp=q.front();
q.pop();
cout<<a[x].name<<" used "<<a[x].c[j].name<<",now p="<<p<<".\n";
a[x].c[j]=tmpp;
for(int k=1;k<=n;k++){
swap(a[k].nxt,a[k].pre);
}
return p+1e6;
}
else if(i==8){
card tmpp=q.front();
q.pop();
cout<<a[x].name<<" used "<<a[x].c[j].name<<",now p="<<p<<".\n";
a[x].c[j]=tmpp;
db=1;
return p+1e6;
}
}
}
}
cout<<a[x].name<<" lost the game.\n";
return 100;
}
int playsmall(int x,int p){
int minn=inf,id=0;
for(int i=6;i<=8;i++){
for(int j=1;j<=3;j++){
tmp=a[x].c[j];
if(tmp.name==nm[i]){
if(i==6){
card tmpp=q.front();
q.pop();
cout<<a[x].name<<" used "<<a[x].c[j].name<<",now p="<<p<<".\n";
a[x].c[j]=tmpp;
return p+1e6;
}
else if(i==7){
card tmpp=q.front();
q.pop();
cout<<a[x].name<<" used "<<a[x].c[j].name<<",now p="<<p<<".\n";
a[x].c[j]=tmpp;
for(int k=1;k<=n;k++){
swap(a[k].nxt,a[k].pre);
}
return p+1e6;
}
else if(i==8){
card tmpp=q.front();
q.pop();
cout<<a[x].name<<" used "<<a[x].c[j].name<<",now p="<<p<<".\n";
a[x].c[j]=tmpp;
db=1;
return p+1e6;
}
}
}
}
for(int i=1;i<=5;i++){
for(int j=1;j<=3;j++){
tmp=a[x].c[j];
if(tmp.name==nm[i]){
int to=p;
if(i==1)to>>=1;
else if(i==2)to-=tmp.num;
else if(i==3)to+=tmp.num;
else if(i==4)to*=tmp.num;
else if(i==5)to=tmp.num;
if(to>99)continue;
if(to<minn){
minn=to;
id=j;
}
}
}
}
if(id){
tmp=q.front();
q.pop();
cout<<a[x].name<<" used "<<a[x].c[id].name<<a[x].c[id].num<<",now p="<<minn<<".\n";
a[x].c[id]=tmp;
return minn;
}
cout<<a[x].name<<" lost the game.\n";
return 100;
}
int main(){
cin>>n>>m>>k;
for(int i=1;i<=n;i++){
cin>>a[i].name;
for(int j=1;j<=3;j++){
a[i].c[j].input();
}
a[i].nxt=i==n?1:i+1;
a[i].pre=i==1?n:i-1;
}
while(k--){
tmp.input();
q.push(tmp);
}
now=1;
for(int t=1;t<=m;t++){
cout<<"Round "<<t<<":\n";
for(int i=1;i<=n;i++){
a[i].nxt=i==n?1:i+1;
a[i].pre=i==1?n:i-1;
}
p=db=0;
while(1){
if(db){
p=playsmall(now,p);
if(p>=1e4){
p=p-1e6;
now=a[now].nxt;
continue;
}
if(p==100)break;
db=0;
}
p=playbig(now,p);
if(p>=1e4)p=p-1e6;
if(p==100){
break;
}
now=a[now].nxt;
}
for(int i=1;i<=3;i++){
tmp=q.front();
q.pop();
a[now].c[i]=tmp;
}
}
return 0;
}
主體思路是對的,但是犯了不少錯導致只有 \(10\) 分。
- 沒考慮負數 \((|p| \le 10^4)\)
- \(\texttt{double}\) 標記未置零
- 要求向下取整,但 c++ 中的除法是向 \(0\) 取整
- 每輪新開始時沒重置方向
這已經不能算掛分了。
T2 mine 0Pts
原題 Minesweeper 1D。
一道分討 DP,但賽時沒想出來,直接記搜了。
然後發現這個新 · 學校題庫開不了 \(10^6 \times 6 \times 6\) 的陣列,會 RE。
但開成 \(10^6 \times 5 \times 5\) 就過了。
幽默網站。
點選檢視程式碼
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e6+5;
const int mod=1e9+7;
string s;
int n;
int f[N][5][5];
int dfs(int x,int lst,int llst){
if(x==n+1){
int ans=1;
if(lst==1&&llst!=3)ans=0;
else if(lst==2)ans=0;
else if(lst==0&&llst==3)ans=0;
return f[x][lst][llst]=ans;
}
if(f[x][lst][llst]!=-1)return f[x][lst][llst];
if(x==0){
int now;
if(x==0)now=4;
else now=(s[x-1]=='*'?3:s[x-1]-'0');
int ans;
if(now==0&&lst==3)ans=0;
else if(now==1&&x==n&&lst!=3)ans=0;
else if(now==2&&lst!=3)ans=0;
else if(now==3&&lst==1&&llst==3)ans=0;
else if(now==3&&lst==0)ans=0;
else if(now!=3&&lst==1&&llst!=3)ans=0;
else if((now!=3||llst!=3)&&lst==2)ans=0;
else ans=dfs(x+1,now,lst);
return f[x][lst][llst]=ans;
}
else if(s[x-1]!='?'){
int now;
if(x==0)now=4;
else now=(s[x-1]=='*'?3:s[x-1]-'0');
int ans;
if(now==0&&lst==3)ans=0;
else if(now==1&&x==n&&lst!=3)ans=0;
else if(now==2&&lst!=3)ans=0;
else if(now==3&&lst==1&&llst==3)ans=0;
else if(now==3&&lst==0)ans=0;
else if(now!=3&&lst==1&&llst!=3)ans=0;
else if((now!=3||llst!=3)&&lst==2)ans=0;
else ans=dfs(x+1,now,lst);
return f[x][lst][llst]=ans;
}
int ans=0;
if(lst==3){
for(int i=1;i<=3;i++)ans=(ans+dfs(x+1,i,lst))%mod;
}
else if(lst==0){
ans=(dfs(x+1,1,lst)+dfs(x+1,0,lst))%mod;
}
else if(lst==1){
if(llst==3)ans=(dfs(x+1,0,lst)+dfs(x+1,1,lst))%mod;
else ans=dfs(x+1,3,lst);
}
else if(lst==2){
ans=dfs(x+1,3,lst);
}
else ans=(dfs(x+1,0,lst)+dfs(x+1,1,lst)+dfs(x+1,3,lst))%mod;
return f[x][lst][llst]=ans%mod;
}
int main(){
memset(f,-1,sizeof(f));
cin>>s;
n=s.size();
cout<<dfs(0,0,0);
return 0;
}
T3 小凱的疑惑 100Pts
題面
數學題,大力手玩找規律推式子即可。
最後結論是:若 \(n\),\(m\) 不互質為 \(-1\),否則為 \(\frac{(n-1)\times(m-1)}{2}\)。
不過 \(O(n)\) 也能過 \(10^8\),沒多測導致的。
賽時直接手模出了最終式。
更詳細的推式子
點選檢視程式碼
#include<bits/stdc++.h>
#define int ll
using namespace std;
typedef long long ll;
int x,y;
main(){
cin>>x>>y;
if(x>y)swap(x,y);
if(x==1||y==1)return cout<<0,0;
if(__gcd(x,y)!=1)return cout<<-1,0;
cout<<(x-1)*(y-1)/2;
return 0;
}
T4 春節十二響 100Pts
原題 春節十二響。
由於選出的數不能存在祖先關係,所以每一“條”上最多選一個;
顯然,我們應該把最大的一堆放在一起,然後是次大的,以此類推。
這是一個自底向上的過程,一次 DFS 就解決了。
注意要用啟發式合併降至 \(O(n\log n)\)。
點選檢視程式碼
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e5+5;
int n,a[N],fa[N];
priority_queue<int> q[N];
struct edge{
int next,to;
}e[N*2];
int h[N],cnt;
void add(int u,int v){
e[++cnt]={h[u],v};
h[u]=cnt;
}
void merge(int x,int y){
if(q[x].size()>q[y].size())swap(q[x],q[y]);
while(!q[x].empty()){
int a=q[x].top(),b=q[y].top();
q[x].pop();q[y].pop();
q[0].push(max(a,b));
}
while(!q[0].empty()){
q[y].push(q[0].top());
q[0].pop();
}
}
void dfs(int x){
for(int i=h[x];i;i=e[i].next){
int to=e[i].to;
dfs(to);
merge(to,x);
}
q[x].push(a[x]);
}
int main(){
cin>>n;
for(int i=1;i<=n;i++)cin>>a[i];
for(int i=2;i<=n;i++){
cin>>fa[i];
add(fa[i],i);
}
dfs(1);
ll ans=0;
while(!q[1].empty()){
ans+=q[1].top();
q[1].pop();
}
cout<<ans;
return 0;
}