PKUSC 模拟赛 day1 下午总结

下午到了机房之后又困又饿,还要被强行摁着看英文题,简直差评

第一题是NOIP模拟赛的原题,随便模拟就好啦

本人模拟功力太渣不小心打错了个变量,居然调了40多分钟QAQ

#include<cstdio>
#include<cstring>
#include<iostream>
#include<cstdlib>
#include<algorithm>
using namespace std;
 
const int maxn=100010;
char s[10][maxn];
int Num[maxn];
int a,b,n,k,now;
 
int check(int L,int R){
    int cnt=0;
    for(int i=1;i<=7;++i)for(int j=L;j<=R;++j)if(s[i][j]=='x')cnt++;
    if(cnt==7)return 1;
    if(cnt==9)return -1;
    if(cnt==11)return 7;
    if(cnt==23)return 8;
    if(cnt==20)return 0;
    if(cnt==14)return 4;
    if(cnt==19){
        if(s[5][L]=='x')return 2;
        if(s[2][L]=='x')return 5;
        return 3;
    }
    if(cnt==21){
        if(s[5][L]=='x')return 6;
        return 9;
    }return 0;
}
void Get_print(int L,int R,int k){
    if(k==0){
        for(int i=L;i<=R;++i)s[1][i]='x',s[7][i]='x';
        for(int i=2;i<=6;++i){
            for(int j=L;j<=R;++j){
                if(j==L||j==R)s[i][j]='x';
                else s[i][j]='.';
            }
        }return;
    }
    if(k==1){
        for(int i=1;i<=7;++i){
            for(int j=L;j<=R;++j){
                if(j==R)s[i][j]='x';
                else s[i][j]='.';
            }
        }return;
    }
    if(k==2){
        for(int i=L;i<=R;++i)s[1][i]=s[4][i]=s[7][i]='x';
        for(int i=2;i<=3;++i){
            for(int j=L;j<=R;++j){
                if(j==R)s[i][j]='x';
                else s[i][j]='.';
            }
        }
        for(int i=5;i<=6;++i){
            for(int j=L;j<=R;++j){
                if(j==L)s[i][j]='x';
                else s[i][j]='.';
            }
        }return;
    }
    if(k==3){
        for(int i=L;i<=R;++i)s[1][i]=s[4][i]=s[7][i]='x';
        for(int i=2;i<=3;++i){
            for(int j=L;j<=R;++j){
                if(j==R)s[i][j]='x';
                else s[i][j]='.';
            }
        }
        for(int i=5;i<=6;++i){
            for(int j=L;j<=R;++j){
                if(j==R)s[i][j]='x';
                else s[i][j]='.';
            }
        }return;
    }
    if(k==4){
        for(int i=1;i<=3;++i){
            for(int j=L;j<=R;++j){
                if(j==L||j==R)s[i][j]='x';
                else s[i][j]='.';
            }
        }
        for(int i=L;i<=R;++i)s[4][i]='x';
        for(int i=5;i<=7;++i){
            for(int j=L;j<=R;++j){
                if(j==R)s[i][j]='x';
                else s[i][j]='.';
            }
        }return;
    }
    if(k==5){
        for(int i=L;i<=R;++i)s[1][i]=s[4][i]=s[7][i]='x';
        for(int i=2;i<=3;++i){
            for(int j=L;j<=R;++j){
                if(j==L)s[i][j]='x';
                else s[i][j]='.';
            }
        }
        for(int i=5;i<=6;++i){
            for(int j=L;j<=R;++j){
                if(j==R)s[i][j]='x';
                else s[i][j]='.';
            }
        }return;
    }
    if(k==6){
        for(int i=L;i<=R;++i)s[1][i]=s[4][i]=s[7][i]='x';
        for(int i=2;i<=3;++i){
            for(int j=L;j<=R;++j){
                if(j==L)s[i][j]='x';
                else s[i][j]='.';
            }
        }
        for(int i=5;i<=6;++i){
            for(int j=L;j<=R;++j){
                if(j==R||j==L)s[i][j]='x';
                else s[i][j]='.';
            }
        }return;
    }
    if(k==7){
        for(int i=L;i<=R;++i)s[1][i]='x';
        for(int i=2;i<=7;++i){
            for(int j=L;j<=R;++j){
                if(j==R)s[i][j]='x';
                else s[i][j]='.';
            }
        }return;
    }
    if(k==8){
        for(int i=L;i<=R;++i)s[1][i]=s[4][i]=s[7][i]='x';
        for(int i=2;i<=3;++i){
            for(int j=L;j<=R;++j){
                if(j==L||j==R)s[i][j]='x';
                else s[i][j]='.';
            }
        }
        for(int i=5;i<=6;++i){
            for(int j=L;j<=R;++j){
                if(j==R||j==L)s[i][j]='x';
                else s[i][j]='.';
            }
        }return;
    }
    if(k==9){
        for(int i=L;i<=R;++i)s[1][i]=s[4][i]=s[7][i]='x';
        for(int i=2;i<=3;++i){
            for(int j=L;j<=R;++j){
                if(j==L||j==R)s[i][j]='x';
                else s[i][j]='.';
            }
        }
        for(int i=5;i<=6;++i){
            for(int j=L;j<=R;++j){
                if(j==R)s[i][j]='x';
                else s[i][j]='.';
            }
        }return;
    }return;
}
void print(int n){
    int len=0,u=n;
    if(!n)Num[++len]=0;
    else{while(n)Num[++len]=n%10,n/=10;}
    for(int i=len;i>=1;--i){
        int L=(len-i)*6+1,R=(len-i+1)*6-1;
        Get_print(L,R,Num[i]);
        for(int j=1;j<=7;++j)s[j][R+1]='.';
    }
    len=len*6-1;
    for(int i=1;i<=7;++i){
        for(int j=1;j<=len;++j){
            putchar(s[i][j]);
        }printf("
");
    }
    return;
}
 
int main(){
    for(int i=1;i<=7;++i)scanf("%s",s[i]+1);
    a=b=0;n=strlen(s[1]+1);k=(n+1)/6;
    now=0;
    for(int i=1;i<=k;++i){
        int L=(i-1)*6+1,R=i*6-1;
        int c=check(L,R);
        if(c==-1)a=now,now=0;
        else now=now*10+c;
    }b=now;
    b=a+b;
    print(b);
    return 0;
}

第二题考场上只想出了对a和b的处理方式,没有想出c的处理方式

貌似c要用NTT,还是模任意质数的NTT,决定去学习一发(坑ing)

第三题考场上并没有做出来,首先题目奇怪的输入保证了每个点的出度均为1,且图中只存在偶环

我们不妨考虑什么样的点一定在集合内,显然如果他入度为0,那么一定在集合内

那么这个点所能到达的点就一定不能选了,把这两个点删掉之后,原图会又出现一些入度为0的点

这样重复若干次之后原图剩下的就只有偶环了,对于偶环我们任取二分图的一侧染色即可

细节略多,自己画画图推一推也能把细节都推出来

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<queue>
using namespace std;
 
const int maxn=200010;
int n,u;
int to[maxn];
int deg[maxn];
int vis[maxn];
int ans[maxn],tot=0;
queue<int>Q;
void toposort(){
    for(int i=1;i<=n;++i)if(deg[i]==0)Q.push(i),vis[i]=1;
    while(!Q.empty()){
        int u=Q.front();Q.pop();
        int now=to[u];
        if(vis[now]!=-1)continue;
        vis[now]=0;
        int v=to[now];deg[v]--;
        if(deg[v]==0&&vis[v]==-1)vis[v]=1,Q.push(v);
    }return;
}
int main(){
    scanf("%d",&n);n<<=1;
    for(int i=1;i<=n;++i){
        scanf("%d",&u);
        to[i]=u;deg[u]++;
    }
    memset(vis,-1,sizeof(vis));
    toposort();
    for(int i=1;i<=n;++i){
        if(vis[i]==-1){
            if(i<=(n>>1))ans[++tot]=i;
        }else{
            if(vis[i])ans[++tot]=i;
        }
    }
    for(int i=1;i<=tot;++i){
        printf("%d",ans[i]);
        if(i==tot)printf("
");
        else printf(" ");
    }return 0;
}

第四题是BC的原题的弱化版

一开始看错题以为求字典序最小的解结果各种挂QAQ

如果这些数有奇数个,sum=中位数*数的数量

如果有偶数个,sum=(首项+尾项)*数的数量/2

都是乘法,枚举因子搞一搞就好啦

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<iostream>
#include<cmath>
using namespace std;
 
const int oo=0x7fffffff;
int T,n;
int L,len;
 
void check(int i){
    int k=n/i;
    if(k&1){
        int now=(i-k/2);
        if(now>0){
            if(k<len&&k!=1)len=k,L=now;
        }
    }
    if(i&1){
        int now=((i>>1)-k+1);
        k<<=1;
        if(now>0){
            if(k<len&&k!=1)len=k,L=now;
        }
    }return;
}
 
int main(){
    scanf("%d",&T);
    while(T--){
        scanf("%d",&n);
        if(n==1){printf("IMPOSSIBLE
");continue;}
        if(n&1){
            printf("%d = ",n);
            printf("%d + %d
",n>>1,(n>>1)+1);
            continue;
        }
        int m=(int)(sqrt(n+0.5))+1;
        L=oo;len=oo;
        for(int i=1;i<=m;++i){
            if(n%i==0){
                check(i);
                if(i*i!=n)check(n/i);
            }
        }
        if(L==oo)printf("IMPOSSIBLE
");
        else{
            printf("%d = ",n);
            for(int i=0;i<len;++i){
                printf("%d ",L+i);
                if(i!=len-1)printf("+ ");
            }printf("
");
        }
    }return 0;
}

第五题首先如果一个轮子被影响,显然比例是第一个轮子的R和这个轮子的R的比

关键是判断逆时针和顺时针,我们发现由于数据造的很好,不存在三个轮子互相相交的情况

那么显然第一个是逆时针,第一个影响到的是顺时针,再影响到的是逆时针。。。BFS一遍即可

#include<cstdio>
#include<cstring>
#include<iostream>
#include<cstdlib>
#include<algorithm>
#include<queue>
#include<cmath>
using namespace std;
 
const int maxn=1010;
int T,n;
int vis[maxn];
struct C{
    double x,y,r;
}c[maxn];
int h[maxn],cnt=0;
struct edge{
    int to,next;
}G[2000010];
queue<int>Q;
int GCD(int a,int b){return b==0?a:GCD(b,a%b);}
void add(int x,int y){
    cnt++;G[cnt].to=y;G[cnt].next=h[x];h[x]=cnt;
}
double dis(const C &A,const C &B){
    return sqrt((A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y));
}
void BFS(){
    Q.push(1);vis[1]=0;
    while(!Q.empty()){
        int u=Q.front();Q.pop();
        for(int i=h[u];i;i=G[i].next){
            int v=G[i].to;
            if(vis[v]!=-1)continue;
            vis[v]=(vis[u]^1);
            Q.push(v);
        }
    }return;
}
int main(){
    scanf("%d",&T);
    while(T--){
        scanf("%d",&n);
        memset(vis,-1,sizeof(vis));
        for(int i=1;i<=n;++i)scanf("%lf%lf%lf",&c[i].x,&c[i].y,&c[i].r);
        memset(h,0,sizeof(h));cnt=0;
        for(int i=1;i<=n;++i){
            for(int j=i+1;j<=n;++j){
                if(dis(c[i],c[j])<=c[i].r+c[j].r){
                    add(i,j);add(j,i);
                }
            }
        }BFS();
        for(int i=1;i<=n;++i){
            if(vis[i]==-1)printf("not moving
");
            else{
                int A=(int)(c[i].r+0.1),B=(int)(c[1].r+0.1);
                int d=GCD(A,B);
                A/=d;B/=d;
                if(A==1)printf("%d ",B);
                else printf("%d/%d ",B,A);
                if(vis[i]==1)printf("counterclockwise
");
                else printf("clockwise
");
            }
        }
    }return 0;
}

第六题我还能说些什么呢,数据范围貌似暴力都可以过去啦

正常点的写法就是矩形面积并的裸题

由于本人忘记了线段树上的标记怎么维护了思考了很久,差点就要写分块了

(不过分块还是很好写的,捂脸。。)

写分块的过程中就领悟了标记怎么维护QAQ,然后写成线段树跑的飞快

#include<cstdio>
#include<cstring>
#include<iostream>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#define eps 1e-4
using namespace std;
 
const int maxn=400010;
int n,kase,cnt,m;
double a,b,cc,d;
double pos[maxn];
struct Seg{
    double l,r,h;
    int type;
}c[maxn];
struct Seg_Tree{
    int cnt;
    double len;
}t[maxn<<2];
bool cmp(const Seg &A,const Seg &B){
    return A.h<B.h;
}
void build(int o,int L,int R){
    t[o].cnt=t[o].len=0;
    if(L==R)return;
    int mid=(L+R)>>1;
    build(o<<1,L,mid);
    build(o<<1,mid+1,R);
}
int Get_pos(double v,int L,int R){
    while(L<=R){
        int mid=(L+R)>>1;
        if(fabs(pos[mid]-v)<eps)return mid;
        else if(v<pos[mid])R=mid-1;
        else L=mid+1;
    }return 0;
}
void Get_len(int o,int L,int R){
    if(t[o].cnt)t[o].len=pos[R+1]-pos[L];
    else if(L==R)t[o].len=0;
    else t[o].len=t[o<<1].len+t[o<<1|1].len;
}
void UPD(int o,int L,int R,int x,int y,int v){
    if(L>=x&&R<=y){
        t[o].cnt+=v;
        Get_len(o,L,R);
        return;
    }
    int mid=(L+R)>>1;
    if(y<=mid)UPD(o<<1,L,mid,x,y,v);
    else if(x>mid)UPD(o<<1|1,mid+1,R,x,y,v);
    else {UPD(o<<1,L,mid,x,y,v);UPD(o<<1|1,mid+1,R,x,y,v);}
    Get_len(o,L,R);
}
 
int main(){
    while(scanf("%d",&n)==1){
        if(!n)break;
        kase++;cnt=0;
        for(int i=0;i<n;i++){
          scanf("%lf%lf%lf%lf",&a,&b,&cc,&d);
          cnt++;
          c[cnt].l=a;c[cnt].r=cc;c[cnt].h=b;c[cnt].type=1;
          pos[cnt]=a;
          cnt++;
          c[cnt].l=a;c[cnt].r=cc;c[cnt].h=d;c[cnt].type=-1;
          pos[cnt]=cc;
        }
        sort(c+1,c+cnt+1,cmp);
        sort(pos+1,pos+cnt+1);
        m=0;pos[0]=-1;
        for(int i=1;i<=cnt;++i){
            if(pos[i]!=pos[i-1])pos[++m]=pos[i];
        }
        build(1,1,m);
        double ans=0;
        for(int i=1;i<=cnt;++i){
            int L=Get_pos(c[i].l,1,m);
            int R=Get_pos(c[i].r,1,m)-1;
            if(L<=R)UPD(1,1,m,L,R,c[i].type);
            ans+=(c[i+1].h-c[i].h)*t[1].len;
        }
        printf("Test case #%d
",kase);
        printf("Total explored area: %.2lf

",ans);
    }return 0;
}

考试中较好的地方:这场考试并没有什么较好的地方

考试中较差的地方:

1、模拟居然需要调试!

2、第三题应该多推导而不是直接套二分图的模型的

3、第五题应该早点看,最后几分钟才写完,真是危险

4、模板还是不熟练,矩形面积并居然差点忘掉

原文地址:https://www.cnblogs.com/joyouth/p/5499217.html