CSP 模拟 1

T1 [start]

原题 P7506 「Wdsr-2.5」琪露诺的算数游戏
大模拟,写完只贴个代码。

点击查看代码
#include<bits/stdc++.h>
typedef long long ll;
typedef unsigned long long ull;
inline int read(){char ch=getchar();int x=0,f=1;for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;for(;ch>='0'&&ch<='9';ch=getchar())x=(x<<3)+(x<<1)+(ch^48);return x*f;}
const int N=105;
int n,m,k,st,top,tag,now,end,P,R;
std::string sk[(int)3e5+10];
inline int SK(std::string s){
if(s.size()==2){return s[1]-'0';}
else {return (s[1]-'0')*10+s[2]-'0';}
}
inline int ne(int x){return ((x+tag+n)%n)?((x+tag+n)%n):n;}
struct PEO{std::string name,c[4];int tag;}p[N];
inline void useno(int id){
int max=-1e9;
for(int i=1;i<=3;++i){
if(p[id].c[i].size()<=3){
int x=SK(p[id].c[i]);
if(p[id].c[i][0]=='A'){
x+=P;
if(x<=99)max=std::max(x,max);
}if(p[id].c[i][0]=='B'){
x=P-x;
if(x<=99)max=std::max(x,max);
}if(p[id].c[i][0]=='C'){
x=P*x;
if(x<=99)max=std::max(x,max);
}if(p[id].c[i].size()<=3&&p[id].c[i][0]=='D'){
x=std::floor(P*1.0/x);
if(x<=99)max=std::max(x,max);
}if(p[id].c[i][0]=='E'){
max=std::max(x,max);
}
}
}
if(max==-1e9){
for(int i=1;i<=3;++i){
if(p[id].c[i]=="PASS"){
std::cout<<p[id].name<<" used PASS,now p="<<P<<".\n";
p[id].c[i]=sk[top++];
return;
}
}
for(int i=1;i<=3;++i){
if(p[id].c[i]=="TURN"){
std::cout<<p[id].name<<" used TURN,now p="<<P<<".\n";
tag*=-1;
p[id].c[i]=sk[top++];
return;
}
}
for(int i=1;i<=3;++i){
if(p[id].c[i]=="DOUBLE"){
std::cout<<p[id].name<<" used DOUBLE,now p="<<P<<".\n";
p[ne(now)].tag=1;
p[id].c[i]=sk[top++];
return;
}
}
std::cout<<p[id].name<<" lost the game.\n";
p[id].c[1]=sk[top++];p[id].c[2]=sk[top++];p[id].c[3]=sk[top++];
end=1;
return;
}
int pd=0;
for(int i=1;i<=3;++i){
int x=SK(p[id].c[i]);
if(p[id].c[i][0]=='C'){
x=P*x;
if(x==max){
P=x;
std::cout<<p[id].name<<" used "<<p[id].c[i]<<",now p="<<P<<".\n";
p[id].c[i]=sk[top++];
p[id].tag=0;
pd=1;
return;
}
}
}
if(!pd){
for(int i=1;i<=3;++i){
int x=SK(p[id].c[i]);
if(p[id].c[i][0]=='A'){
x=P*1.0+x;
if(x==max){
P=x;
std::cout<<p[id].name<<" used "<<p[id].c[i]<<",now p="<<P<<".\n";
p[id].c[i]=sk[top++];
p[id].tag=0;
pd=1;
return;
}
}
}
}
if(!pd){
for(int i=1;i<=3;++i){
int x=SK(p[id].c[i]);
if(p[id].c[i][0]=='B'){
x=P-x;
if(x==max){
P=x;
std::cout<<p[id].name<<" used "<<p[id].c[i]<<",now p="<<P<<".\n";
p[id].c[i]=sk[top++];
p[id].tag=0;
pd=1;
return;
}
}
}
}
if(!pd){
for(int i=1;i<=3;++i){
int x=SK(p[id].c[i]);
if(p[id].c[i].size()<=3&&p[id].c[i][0]=='D'){
x=std::floor(P*1.0/x);
if(x==max){
P=x;
std::cout<<p[id].name<<" used "<<p[id].c[i]<<",now p="<<P<<".\n";
p[id].c[i]=sk[top++];
p[id].tag=0;
pd=1;
return;
}
}
}
}
if(!pd){
for(int i=1;i<=3;++i){
int x=SK(p[id].c[i]);
if(p[id].c[i][0]=='E'){
if(x==max){
P=x;
std::cout<<p[id].name<<" used "<<p[id].c[i]<<",now p="<<P<<".\n";
p[id].c[i]=sk[top++];
p[id].tag=0;
return;
}
}
}
}
}
inline void use(int id){
if(p[id].tag){
for(int i=1;i<=3;++i){
if(p[id].c[i]=="PASS"){
std::cout<<p[id].name<<" used PASS,now p="<<P<<".\n";
p[id].c[i]=sk[top++];
p[id].tag=0;
p[ne(now)].tag=1;
return;
}
}
for(int i=1;i<=3;++i){
if(p[id].c[i]=="TURN"){
std::cout<<p[id].name<<" used TURN,now p="<<P<<".\n";
tag*=-1;
p[id].c[i]=sk[top++];
p[id].tag=0;
p[ne(now)].tag=1;
return;
}
}
for(int i=1;i<=3;++i){
if(p[id].c[i]=="DOUBLE"){
std::cout<<p[id].name<<" used DOUBLE,now p="<<P<<".\n";
p[ne(now)].tag=1;
p[id].c[i]=sk[top++];
p[id].tag=0;
return;
}
}
int min=100;
for(int i=1;i<=3;++i){
if(p[id].c[i].size()<=3){
int x=SK(p[id].c[i]);
if(p[id].c[i][0]=='A'){
x+=P;
if(x<=99)min=std::min(x,min);
}if(p[id].c[i][0]=='B'){
x=P-x;
if(x<=99)min=std::min(x,min);
}if(p[id].c[i][0]=='C'){
x=P*x;
if(x<=99)min=std::min(x,min);
}if(p[id].c[i].size()<=3&&p[id].c[i][0]=='D'){
x=std::floor(P*1.0/x);
if(x<=99)min=std::min(x,min);
}if(p[id].c[i][0]=='E'){
min=std::min(x,min);
}
}
}
if(min>99){
std::cout<<p[id].name<<" lost the game.\n";
p[id].c[1]=sk[top++];p[id].c[2]=sk[top++];p[id].c[3]=sk[top++];
end=1;
return ;
}
int pd=0;
for(int i=1;i<=3;++i){
int x=SK(p[id].c[i]);
if(p[id].c[i].size()<=3&&p[id].c[i][0]=='D'){
x=std::floor(P*1.0/x);
if(x==min){
P=x;
std::cout<<p[id].name<<" used "<<p[id].c[i]<<",now p="<<P<<".\n";
p[id].c[i]=sk[top++];
p[id].tag=0;
pd=1;
break;
}
}
}
if(!pd){
for(int i=1;i<=3;++i){
int x=SK(p[id].c[i]);
if(p[id].c[i][0]=='B'){
x=P-x;
if(x==min){
P=x;
std::cout<<p[id].name<<" used "<<p[id].c[i]<<",now p="<<P<<".\n";
p[id].c[i]=sk[top++];
p[id].tag=0;
pd=1;
break;
}
}
}
}
if(!pd){
for(int i=1;i<=3;++i){
int x=SK(p[id].c[i]);
if(p[id].c[i][0]=='A'){
x=P*1.0+x;
if(x==min){
P=x;
std::cout<<p[id].name<<" used "<<p[id].c[i]<<",now p="<<P<<".\n";
p[id].c[i]=sk[top++];
p[id].tag=0;
pd=1;
break;
}
}
}
}
if(!pd){
for(int i=1;i<=3;++i){
int x=SK(p[id].c[i]);
if(p[id].c[i][0]=='C'){
x=P*x;
if(x==min){
P=x;
std::cout<<p[id].name<<" used "<<p[id].c[i]<<",now p="<<P<<".\n";
p[id].c[i]=sk[top++];
p[id].tag=0;
pd=1;
break;
}
}
}
}
if(!pd){
for(int i=1;i<=3;++i){
int x=SK(p[id].c[i]);
if(p[id].c[i][0]=='E'){
if(x==min){
P=x;
std::cout<<p[id].name<<" used "<<p[id].c[i]<<",now p="<<P<<".\n";
p[id].c[i]=sk[top++];
p[id].tag=0;
break;
}
}
}
}
useno(id);
}else{useno(id);}
}
signed main(){
// freopen("P7506_10.in","r",stdin);freopen("out.out","w",stdout);
std::ios::sync_with_stdio(false);std::cin.tie(0);std::cout.tie(0);
std::cin>>n>>m>>k;
for(int i=1;i<=n;++i)std::cin>>p[i].name>>p[i].c[1]>>p[i].c[2]>>p[i].c[3];
for(int i=1;i<=k;++i)std::cin>>sk[++top];
top=1;tag=1;now=1;
for(int i=1;i<=m;++i){
std::cout<<"Round "<<i<<":"<<'\n';
while(1){
use(now);
if(end){
end=0;tag=1;P=0;
for(int j=1;j<=n;++j)p[j].tag=0;
break;
}
now=ne(now);
}
}
}
妈了,题读不对,选完之后没标记又选调半天。红温。

T2 mine (CF404D Minesweeper 1D )

0,1,2,3 分别表示周围 0 个雷,1 个雷,2 个雷,自己是雷。
f[i][j][k] 表示到第 i 个数,前 i2 个数合法且第 i1 个数为 j,第 i 个数为 k 的方案数。
特别的,f[i][0][0] 表示第 i 位是 0 的方案数。显然有状态转移方程:

{f[i][0][0]=f[i1][0][0]+f[i1][3][1]f[i][0][1]=f[i1][0][0]f[i][1][1]=f[i1][3][1]f[i][3][1]=f[i1][1][3]+f[i1][2][3]+f[i1][3][3]f[i][3][2]=f[i1][1][3]+f[i1][2][3]+f[i1][3][3]f[i][1][3]=f[i1][0][1]+f[i1][1][1]f[i][2][3]=f[i1][3][2]f[i][3][3]=f[i1][1][3]+f[i1][2][3]+f[i1][3][3]

一些非法状态不需要考虑。

点击查看代码
#include<bits/stdc++.h>
#define int long long
typedef long long ll;
typedef unsigned long long ull;
inline int read(){char ch=getchar();int x=0,f=1;for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;for(;ch>='0'&&ch<='9';ch=getchar())x=(x<<3)+(x<<1)+(ch^48);return x*f;}
const int N=1e6+10,mod=1e9+7;
char s[N];
int a[N],f[N][4][4];
inline int mo(int x){return x<0?(x%mod+mod)%mod:(x>=mod?x%mod:x);}
signed main(){
// freopen("in.in","r",stdin);freopen("out.out","w",stdout);
std::ios::sync_with_stdio(false);std::cin.tie(0);std::cout.tie(0);
std::cin>>s+1;
int n=strlen(s+1);
for(int i=1;i<=n;++i){
a[i]=s[i]-'0';
if(s[i]=='*')a[i]=3;
if(s[i]=='?')a[i]=4;
}
if(!a[1]||a[1]==4){
f[1][0][0]=1;
}if(a[1]==1||a[1]==4){
f[1][0][1]=1;
}if(a[1]==3||a[1]==4){
f[1][1][3]=1;
}
for(int i=2;i<=n;++i){
if(!a[i]||a[i]==4){
f[i][0][0]=mo(f[i-1][0][0]+f[i-1][3][1]);
}
if(a[i]==1||a[i]==4){
f[i][0][1]=f[i-1][0][0];
f[i][1][1]=f[i-1][3][1];
f[i][3][1]=mo(f[i-1][1][3]+f[i-1][2][3]+f[i-1][3][3]);
}
if(a[i]==2||a[i]==4){
f[i][3][2]=mo(f[i-1][1][3]+f[i-1][2][3]+f[i-1][3][3]);
}
if(a[i]==3||a[i]==4){
f[i][1][3]=mo(f[i-1][0][1]+f[i-1][1][1]);
f[i][2][3]=f[i-1][3][2];
f[i][3][3]=mo(f[i-1][1][3]+f[i-1][2][3]+f[i-1][3][3]);
}
}
std::cout<<mo(f[n][0][0]+f[n][3][1]+f[n][1][3]+f[n][2][3]+f[n][3][3])<<'\n';
}

T3 小凯的疑惑

根据裴蜀定理,不定方程 ax+by=sum,当且仅当 gcd(x,y)sum 时有解,所以不互质的直接判就行。
对于互质的,kxmody 组成了 y 的完系,所以当余数 p 出现后,所有的 ansmody=p 都是非法的。因为它一定可以表示为 ax+by 的形式,只需要在 ax 前添若干个 y 即可。
所以对于每一个余数考虑,假设 kxmody=p,对于所有的 ansmody=p 只有在余数 p 第一次出现之前的合法,所以考虑有多少个 ykx 之前,即 [0,kxy1],有 kxy 种。
所以最后就是求这个

i=0y1ixy=i=0y1ix(ixmody)y=i=0y1ixyi=0y1iy=i=0y1i(x1)y=(x1)i=0y1iy=(x1)(y1)2

赛时写了 O(n),逆天评测机还没本地快,一秒跑不了裸的 2e8,把循环展开就过了,把 2 的常数消了也过了,就是赛时过不了,挂了 90,300->210,喃泵。

T4 春节十二响

首先考虑策略,对于一条链的,显然是将左右两边候选的排好序后,贪心的大的匹配大的,小的匹配小的。很容易扩展到树上。
考虑对于每一个节点建立一个优先队列 qi,对于一个节点就是将它的儿子的优先队列一一合并,最后将当前点加入到合并后的优先队列中。
正确性比较显然,但是时间复杂度是可以卡到 O(n2logn) 的,发现有很多东西不必重建,只需要继承即可,并且显然可以启发式合并。
具体来说,用 poi 表示节点 i 指向的优先队列编号,合并过程中实时更新,尽量让小去合并大。因为这题每个点都只会进出一次,所以时间复杂度是 O(nlogn)

点击查看代码
#include<bits/stdc++.h>
#define int long long
typedef long long ll;
typedef unsigned long long ull;
inline int read(){char ch=getchar();int x=0,f=1;for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;for(;ch>='0'&&ch<='9';ch=getchar())x=(x<<3)+(x<<1)+(ch^48);return x*f;}
const int N=2e5+10;
int n,w[N],po[N];
std::vector<int> e[N],v1,v2,v3;
std::priority_queue<int> q[N];
inline void dfs(int u){
for(int v:e[u]){
dfs(v);
int l=po[u],r=po[v];
if(q[l].size()<q[r].size()){std::swap(po[u],po[v]),std::swap(l,r);}
while(!q[l].empty()&&!q[r].empty()){
int x=q[l].top(),y=q[r].top();q[l].pop(),q[r].pop();
v3.push_back(std::max(x,y));
}
for(int x:v3)q[l].push(x);
v3.clear();
}
q[po[u]].push(w[u]);
}
signed main(){
// freopen("in.in","r",stdin);freopen("out.out","w",stdout);
std::ios::sync_with_stdio(false);std::cin.tie(0);std::cout.tie(0);
n=read();
for(int i=1;i<=n;++i)po[i]=i;
for(int i=1;i<=n;++i)w[i]=read();
for(int i=2;i<=n;++i){
e[read()].push_back(i);
}
dfs(1);
int ans=0;
while(!q[po[1]].empty()){
ans+=q[po[1]].top();q[po[1]].pop();
}
std::cout<<ans<<'\n';
}
posted @   Ishar-zdl  阅读(59)  评论(6编辑  收藏  举报
相关博文:
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· .NET10 - 预览版1新功能体验(一)
点击右上角即可分享
微信分享提示