2019 年「计算机科学与工程学院」新生赛 暨ACM集训队选拔赛 # 1

T1 请问这还是纸牌游戏吗 https://scut.online/p/567

这道题正解据说是方根 这里先放着等以后填坑吧qwq

但是由于这道题数据是随机的 所以其实是有各种水法的(但是我比赛根本没有想到任何水法qwq

第一种水法呢 因为数据随机 所以当数据大小变得比较大的时候 基本乘出来的数已经能覆盖1到P-1了 所以我们直接输出1和P-1就可以了

而数据比较小的时候就可以暴力计算了qwq

include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#define LL long long
using namespace std;
const int M=2e6+7;
int read(){
    int ans=0,f=1,c=getchar();
    while(c<‘0‘||c>‘9‘){if(c==‘-‘) f=-1; c=getchar();}
    while(c>=‘0‘&&c<=‘9‘){ans=ans*10+(c-‘0‘); c=getchar();}
    return ans*f;
}
LL mod,n,m;
int v1[M],v2[M],cnt1,cnt2;
LL h1[M],h2[M];
int main(){
    LL x;
    mod=read(); n=read(); m=read();
    for(int i=1;i<=n;i++){
        x=read();
        if(!v1[x]) v1[x]=1,h1[++cnt1]=x;
    }
    for(int i=1;i<=m;i++){
        x=read();
        if(!v2[x]) v2[x]=1,h2[++cnt2]=x;
    }
    if(cnt1*cnt2>(5e7)){printf("1 %d\n",mod-1); return 0;}
    LL ans1=mod-1,ans2=0;
    for(int i=1;i<=cnt1;i++)
        for(int j=1;j<=cnt2;j++){
            ans1=min(ans1,h1[i]*h2[j]%mod);
            ans2=max(ans2,h1[i]*h2[j]%mod);
        }
    printf("%lld %lld\n",ans1,ans2);
    return 0;
}

第二种写法呢 我们就可以从枚举P-1开始枚举答案最大是多少 然后枚举每一个a i 看是否存在b i 使得ab%P==枚举的答案

这里利用费马小定理预处理好了每一个a i对应的逆元fv i 所以可以根据枚举的答案和a i直接计算出b所对应的值

然后判断这个值是否存在就可以啦

这样子写的话想要卡掉其实是非常困难的 因为如果答案在中间部分(需要枚举大概n/2次答案()

那么一定会存在很多重复的数 而我们一开始就可以先把重复数去掉(也就是去重)

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#define LL long long
using namespace std;
const int M=2e6+7;
int read(){
    int ans=0,f=1,c=getchar();
    while(c<‘0‘||c>‘9‘){if(c==‘-‘) f=-1; c=getchar();}
    while(c>=‘0‘&&c<=‘9‘){ans=ans*10+(c-‘0‘); c=getchar();}
    return ans*f;
}
LL mod,n,m;
int v1[M],v2[M],cnt1,cnt2;
LL h1[M],h2[M],fv[M];
LL qmod(LL a,LL b){
    LL ans=1;
    while(b){
        if(b&1) ans=ans*a%mod;
        b>>=1;
        a=a*a%mod;
    }
    return ans;
}
int main(){
    LL x,ans1,ans2,f;
    mod=read(); n=read(); m=read();
    for(int i=1;i<=n;i++){
        x=read();
        if(!v1[x]){
            v1[x]=1;
            h1[++cnt1]=x;
            fv[i]=qmod(x,mod-2);
        }
    }
    for(int i=1;i<=m;i++){
        x=read();
        if(!v2[x]) v2[x]=1,h2[++cnt2]=x;
    }
    for(f=0,ans1=1;;ans1++){
        for(int i=1;i<=cnt1;i++)
        if(v2[ans1*fv[i]%mod]){f=1; break;}
        if(f) break;
    }
    for(f=0,ans2=mod-1;;ans2--){
        for(int i=1;i<=cnt1;i++)
        if(v2[ans2*fv[i]%mod]){f=1; break;}
        if(f) break;
    }
    printf("%lld %lld\n",ans1,ans2);
    return 0;
}

T2 请问你喜欢跑步吗 https://scut.online/p/568

这道题就很明显是道水题了 找出每秒所有面包店中价值最大的面包 然后求和就可以了

#include<cstdio>
#include<cstring>
#include<queue>
#include<cmath>
#include<algorithm>
#define LL long long
#define lowbit(x) x&-x
using namespace std;
const int M=507;
int read(){
    int ans=0,f=1,c=getchar();
    while(c<‘0‘||c>‘9‘){if(c==‘-‘) f=-1; c=getchar();}
    while(c>=‘0‘&&c<=‘9‘){ans=ans*10+(c-‘0‘); c=getchar();}
    return ans*f;
}
int n,m;
LL ans,s[M][M],k[M][M];
int main(){
    n=read(); m=read();
    for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) s[i][j]=read();
    for(int i=1;i<=m;i++){
        LL sum=0;
        for(int x=1;x<=n;x++) sum=max(sum,s[x][i]);
        ans+=sum;
    }
    printf("%lld\n",ans);
    return 0;
}

T3 请问穿着熊厉害吗 https://scut.online/p/569

这道题枚举到 √n就可以了

n到n-1 会对应大于 √n的另一段 具体的话通过手动模拟应该能有所体会 细节还是蛮多的

#include<cstdio>
#include<cstring>
#include<queue>
#include<cmath>
#include<algorithm>
#include<set>
#define LL long long
using namespace std;
LL read(){
    LL ans=0,f=1,c=getchar();
    while(c<‘0‘||c>‘9‘){if(c==‘-‘) f=-1; c=getchar();}
    while(c>=‘0‘&&c<=‘9‘){ans=ans*10+(c-‘0‘); c=getchar();}
    return ans*f;
}
LL T,n,q,ans,last,G,x;
int main(){
    T=read();
    while(T--){
        n=read();
        if(n==1){puts("2"); continue;}
        q=2*n; ans=q+n; last=n;
        //printf("%lld\n",ans);
        for(x=3;x*x<=q;x++){
            ans+=q/x;
            if(q%x) G=q/x;
            else G=q/x;
            ans=ans+(x-1)*(last-G);
            //printf("%d %d\n",last,G);
            last=G;
        }
        ans+=(last-x+1)*(x-1);
        printf("%lld\n",ans);
        //printf("%lld %lld\n",last,x);
    }
    return 0;
}

T4 请问机关锁打得开吗 https://scut.online/p/570

这道题9个锁 每个锁4种状态 一共也就2^18种状态 利用二进制来表示每一种状态

比如第一位和第二位表示第一个锁的状态也就是

00表示状态1

01表示状态2

10表示状态3

11表示状态四

以此类推 然后用bfs扫一遍就可以得到答案了

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#define LL long long
using namespace std;
const int Q=17,P=(1<<19)+7;
int read(){
    int ans=0,f=1,c=getchar();
    while(c<‘0‘||c>‘9‘){if(c==‘-‘) f=-1; c=getchar();}
    while(c>=‘0‘&&c<=‘9‘){ans=ans*10+(c-‘0‘); c=getchar();}
    return ans*f;
}
int S,p[Q],s[Q][Q];
int G(int k,int x){
    int w=0;
    if(k&(1<<(2*x))) w+=2;
    if(k&(1<<(2*x-1))) w+=1;
    return w;
}
void nsp(int &k,int x,int w){
    if(k&(1<<(2*x)))    k-=(1<<(2*x));
    if(k&(1<<(2*x-1)))  k-=(1<<(2*x-1));
    if(w&1) k+=(1<<(2*x-1));
    if(w&(1<<1)) k+=(1<<(2*x));
}
int vis[P],d[P],ans=-1;
queue<int>q;
void bfs(){
    q.push(S); vis[S]=1; d[S]=0;
    while(!q.empty()){
        int MM=q.front(); q.pop();
        if(!MM){ans=d[MM]; break;}
        for(int x=1;x<=9;x++){
            int M=MM,w=G(M,x),T=s[x][w],l=G(M,T);
            w=(w+1)%4; l=(l+1)%4;
            nsp(M,x,w); nsp(M,T,l);
            if(!vis[M]) vis[M]=1,d[M]=d[MM]+1,q.push(M);
        }
    }
}
int main(){
    for(int i=1;i<=9;i++){
        p[i]=read()-1;
        for(int j=0;j<=3;j++) s[i][j]=read();
    }
    for(int i=1;i<=9;i++) nsp(S,i,p[i]);
    bfs(); printf("%d\n",ans);
    return 0;
}

T5 请问直方图里能画矩形吗 https://scut.online/p/571

这道题的话 对每一个位置 找出他向左向右所能延申的最远距离就好了

可以用单调栈维护

考虑向左的延申的情况 我们考虑从1位置扫到i(当前)位置

如果一个位置j 他的高度h【j】比你大 并且他位置在你之前(j<I)那么他就可以被忽略

因为要从右边经过你的话 最大高度也就只能是h【i】

向右同理

通过这样的方法我们就可以维护出每一个点向左向右所能延申的最远距离了

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<cmath>
#define LL long long
using namespace std;
const int M=1e6+7;
int read(){
    int ans=0,f=1,c=getchar();
    while(c<‘0‘||c>‘9‘){if(c==‘-‘) f=-1; c=getchar();}
    while(c>=‘0‘&&c<=‘9‘){ans=ans*10+(c-‘0‘); c=getchar();}
    return ans*f;
}
LL n,h[M],stk[M],top,l[M],r[M],ans;
int main(){
    n=read();
    stk[0]=0;
    for(int i=1;i<=n;i++) h[i]=read();
    for(int i=1;i<=n;i++){
        while(top&&h[stk[top]]>=h[i]) top--;
        l[i]=stk[top]+1;
        stk[++top]=i;
        //for(int x=1;x<=top;x++) printf("%d ",h[stk[x]]); puts("");
    }
    top=0; stk[0]=n+1;
    for(int i=n;i>=1;i--){
        while(top&&h[stk[top]]>=h[i]) top--;
        r[i]=stk[top]-1;
        stk[++top]=i;
    }
    //for(int i=1;i<=n;i++) printf("%d %d\n",l[i],r[i]);
    for(int i=1;i<=n;i++) ans=max(ans,(r[i]-l[i]+1)*h[i]);
    printf("%lld\n",ans);
    return 0;
}

当然我比赛的时候脑子一抽就用了set维护

就是将所有的点按从小到大排序 然后从最小开始枚举 将枚举到的点的位置丢到set的里面

这样到当前点时 所有高度比他小的点就已经被丢到set里面的 你就只需要找位置离你最近的点是谁就好了

这个用lower_bound实现的okay了 当然这样写复杂度要多一个log

#include<cstdio>
#include<cstring>
#include<queue>
#include<cmath>
#include<algorithm>
#include<set>
#define LL long long
using namespace std;
const int M=1e6+7;
LL read(){
    LL ans=0,f=1,c=getchar();
    while(c<‘0‘||c>‘9‘){if(c==‘-‘) f=-1; c=getchar();}
    while(c>=‘0‘&&c<=‘9‘){ans=ans*10+(c-‘0‘); c=getchar();}
    return ans*f;
}
LL n,r[M],ans,sum[M],l[M];
struct node{LL id,h;}e[M];
bool cmp(node a,node b){return a.h==b.h?a.id<b.id:a.h<b.h;}
set<LL>q;
set<LL>::iterator It;
int main(){
    n=read();
    for(int i=1;i<=n;i++) e[i].h=read(),e[i].id=i;
    sort(e+1,e+1+n,cmp);
    for(int i=1;i<=n;i++){
        if(q.empty()) r[e[i].id]=n+1;
        else{
            It=q.end();
            if(*--It<e[i].id) r[e[i].id]=n+1;
            else r[e[i].id]=*q.upper_bound(e[i].id);
        }
        //sum[e[i].id]=e[i].h*(r[e[i].id]-e[i].id);
        q.insert(e[i].id);
    }
    q.clear();
    for(int i=1;i<=n;i++){
        if(q.empty()) l[e[i].id]=0;
        else{
            It=q.end();
            if(*--It<(-e[i].id)) l[e[i].id]=0;
            else l[e[i].id]=*q.upper_bound(-e[i].id)*-1;
        }
        //sum[e[i].id]=e[i].h*(r[e[i].id]-e[i].id);
        q.insert(-e[i].id);
    }
    //for(int i=1;i<=n;i++) printf("%d %d\n",l[i],r[i]);
    for(int i=1;i<=n;i++) sum[e[i].id]=e[i].h*(r[e[i].id]-l[e[i].id]-1);
    for(int i=1;i<=n;i++) ans=max(ans,sum[i]);
    printf("%lld\n",ans);
    return 0;
}

T5  留坑待补

T6 留坑待补

T7  请问这是鸽子吗 https://scut.online/p/574

这道题的话 一共就26种字母 我们考虑将26种字母单独维护

对于每个字母 用一个树状数组维护前缀一共有多少个相同的xx(x为当前字母)对 当然 如aaa算两对

xx对以后一个位置作为代表参与计算

然后每次修改则涉及四次修改  删除两次 插入两次 看是否有xx对被破坏 或者是否有xx对形成

然后询问的时候26种各求一次就okay了 当然求和的时候注意细节 如原本为aaaaa的一段

求后三个位置(即aaa)的aa对数时 求出来应为3对 但是因为第一个a的前一位被切断了 所以需要减去1 即为2对

这个细节在求和时是需要注意的

#include<cstdio>
#include<cstring>
#include<queue>
#include<cmath>
#include<algorithm>
#define LL long long
#define lowbit(x) x&-x
using namespace std;
const int M=1e6+7,N=2e5+7;
int read(){
    int ans=0,f=1,c=getchar();
    while(c<‘0‘||c>‘9‘){if(c==‘-‘) f=-1; c=getchar();}
    while(c>=‘0‘&&c<=‘9‘){ans=ans*10+(c-‘0‘); c=getchar();}
    return ans*f;
}
char c[M];
int m,n;
int s[26][N];
void add(int w,int x,int v){
    //printf("%d %d %d\n",w,x,v);
    while(x<=n){
        s[w][x]+=v;
        x+=lowbit(x);
    }
    //for(int i=1;i<=n;i++) printf("%d ",s[w][i]); puts("");
}
int p_sum(int w,int x){
    int ans=0;
    while(x) ans+=s[w][x],x-=lowbit(x);
    return ans;
}
int main(){
    scanf("%s",c+1);
    n=strlen(c+1);
    for(int i=2;i<=n;i++) if(c[i]==c[i-1]) add(c[i]-‘a‘,i,1);//puts("qwq");
    //for(int i=1;i<=n;i++) printf("%d ",s[1][i]);
    //printf("%d\n",p_sum(1,15));
    int op,x,y,q;
    m=read();
    while(m--){
        op=read(); x=read();
        if(op==1){
            q=getchar();
            if(c[x]==q) continue;
            if(c[x]==c[x-1]) add(c[x]-‘a‘,x,-1);
            if(c[x]==c[x+1]) add(c[x]-‘a‘,x+1,-1);
            c[x]=q;
            if(c[x]==c[x-1]) add(c[x]-‘a‘,x,1);
            if(c[x]==c[x+1]) add(c[x]-‘a‘,x+1,1);
        }
        else{
            y=read();
            int ans=0;
            for(int i=0;i<26;i++){
                int now=p_sum(i,y)-p_sum(i,x-1);
                //printf("%d %d\n",p_sum(i,y),p_sum(i,x-1));
                if(now==1&&c[x]==(‘a‘+i)&&c[x]==c[x-1]) now=0;
                if(now) ans+=1;
            }
            printf("%d\n",ans);
        }
    }
    return 0;
}

T8 请问我可以用左手吗 https://scut.online/p/575

这道题就是单纯的高精度加法了

#include<cstdio>
#include<cstring>
#include<queue>
#include<cmath>
#include<algorithm>
#define LL long long
#define lowbit(x) x&-x
using namespace std;
int read(){
    int ans=0,f=1,c=getchar();
    while(c<‘0‘||c>‘9‘){if(c==‘-‘) f=-1; c=getchar();}
    while(c>=‘0‘&&c<=‘9‘){ans=ans*10+(c-‘0‘); c=getchar();}
    return ans*f;
}
char a[507],b[507],c[507],d[507];
int la,lb,lc,ld,mx,now;
int main(){
    scanf("%s",a+1); la=strlen(a+1);
    scanf("%s",b+1); lb=strlen(b+1);
    scanf("%s",c+1); lc=strlen(c+1);
    mx=max(la,lb); mx=max(lc,mx);
    while(mx){
        int sum=now;
        mx--;
        if(la) sum+=(a[la]-‘0‘),la--;
        if(lb) sum+=(b[lb]-‘0‘),lb--;
        if(lc) sum+=(c[lc]-‘0‘),lc--;
        now=sum/10;
        d[++ld]=sum%10;
    }
    if(now) d[++ld]=now;
    for(int i=ld;i>=1;i--) printf("%d",d[i]);
    return 0;
}

T9 请问你强吗 https://scut.online/p/576

这道题就是单纯判断某些字母的出现次数

https://scut.online/p/576

原文地址:https://www.cnblogs.com/yourinA/p/11967985.html

时间: 2024-10-13 17:01:20

2019 年「计算机科学与工程学院」新生赛 暨ACM集训队选拔赛 # 1的相关文章

北方民族大学计算机科学与工程学院研究生导师

北方民族大学计算机科学与工程学院研究生导师(排名不分先后): 保文星教授,何丰教授,石奋苏教授,陶铮教授,姜久雷教授,张春梅教授,杨军教授,杨德仁教授. 北方民族大学计算机科学与工程学院研究生导师:保文星教授 北方民族大学计算机科学与工程学院研究生导师:何丰教授 北方民族大学计算机科学与工程学院研究生导师:石奋苏教授 北方民族大学计算机科学与工程学院研究生导师:陶铮教授 北方民族大学计算机科学与工程学院研究生导师:姜久雷教授 北方民族大学计算机科学与工程学院研究生导师:张春梅教授 北方民族大学计

写给湖南科技大学计算机科学与工程学院2014级物联网工程专业一班

各位学弟学妹,你们即将步入4年的大学生活. 个人认为,大学是一个可以自己主宰人生的地方,大家千万不要认为大学是一个可以随意玩耍,没有高中那般压力生活的阶段,相反的,只要作为一个有进取心的人,压力无处不在,同样巨大,大学的压力在于自己的将来该何去何从.大学是一个有绝对自由的地方,可以说,你可以自己决定有压力没压力,要学习还是不学习,学这些还是那些,怎样学......与高中不同的是,自己可以调整转化压力存在的方式,你可以随时去放松,比如今天学习累了,明天就可以自己休息会儿,而高中的时候却不行,类如此

2019年华南理工大学软件学院ACM集训队选拔赛 Round1

TIps: 1.所有代码中博主使用了scanf和printf作为输入输出  2.代码中使用了define LL long long 所以在声明变量的时候 LL其实就等价于long long 希望这两点不会成为读者看代码时候的障碍qwq 另外题目链接我会放在最后 如果需要请往下拖一拖 T1  这道题其实就是单纯对数据进行排序,但是因为关键字不止一种(解题数m和罚时t) 并且输出的是队伍的名字(也就是序号) 而正常排序完之后我们就会发现 我们并不知道当前各个位置的数对应的队伍名是什么了(也就是其原本

宜信技术学院上榜「2019中国技术品牌影响力企业榜」

12月25日,开发者社区和专业技术媒体SegmentFault发布了2019 中国技术品牌影响力企业榜.凭借过去一年对宜信科技成果和技术实践的传播以及在金融科技领域探索方面的积极努力,宜信技术学院登上榜单前10. 宜信技术学院成立于2017年,专注于分享与传播宜信技术团队的研发实践成果与技术解决方案.经过多年的探索和实践,宜信技术团队沉淀了海量的软件研发经验,特别是在金融科技领域,积极探索软件技术在金融服务与金融安全保障方面的智能化.创新性的技术解决方案,并取得了非常多的技术成果.2019年,围

带你从二次元的角度看建筑「摩根·帝巢丨湛江工程资质×××」

我从小到大是个十足的动漫迷,从小学开始迷恋日本漫画直至现在.从<哆啦A梦>.<樱桃小丸子>这批经典到后来的<海贼王>.<火影忍者>这批灌输热血的鸡汤--但如今似乎更流行二次元动漫. 二次元动漫不仅盛产帅哥美女,还有就是美到让人停止呼吸的建筑!带你从二次元的角度看建筑「摩根·帝巢丨湛江工程资质×××」 引人入胜的故事情节.个性另类的角色设定自然是一部动漫制作成功的必要元素,但是,二次元动漫中呈现的各种或空灵的或美轮美奂的建筑群,也无一不给人以崇高的感觉. 如果

互联网公司的2019年「春潮」:谁迎风逐浪,谁黯然退潮?

用一个词来形容过去一年的中国互联网,大概就是「波涛汹涌」.短短时间,中国互联网产业格局已经悄然发生改变.在 2019 年的金三银四求职季,小千结合一些求职案例,带领大家回顾一下 2018 年至今中国互联网企业的变迁,希望为大家的求职带来些许帮助. 一.大厂的中年危机,猝不及防一口「凉」 代表公司:网易 与传统行业相比,互联网向来是「年轻」与「不安分」的代名词.但是在互联网界,也有一些公司因为人员流动率低.工作节奏慢被誉为互联网里的「国企」.网易.新浪就是其中的典型代表. 尤其是网易,「一入猪场胖

WAIC | 奇点云携「酷炫AI应用」亮相2019世界人工智能大会

你是否还在疑惑“人工智能可否改变世界?” 那么,你该有一些危机感了. 机器视觉.自然语言处理.智能语音.机器人问诊.智慧驾驶……这些AI技术及应用早已渗入了我们日常生活的点滴. 29日,以「智联世界,无限可能」为主题的2019世界人工智能大会(WAIC)在上海开幕.围绕智能领域的技术前沿.产业趋势和热点问题发表演讲和进行高端对话,打造世界顶尖的智能合作交流平台.作为全球顶级人工智能峰会,WAIC已经成为最活跃的AI产业合作平台,华为.BAT.亚马逊.特斯拉等众多行业领军企业将亮相峰会现场. 汇聚

数澜携手中金所,机器学习推动「监管科技3.0」深入发展

近日,中国金融期货交易所(简称「中金所」)与数澜科技签署合作协议,基于数澜旗下数栖·算法平台,共同推进中金所机器学习平台及算法模型建设,构建金融监管科技智能分析能力.这也是在证监会推出以大数据.人工智能及云计算技术为核心的「监管科技3.0」背景下,中金所携手合作伙伴,共同进行机器学习在监管科技应用领域探索与应用的战略变革项目. 中金所是经×××同意,中国证监会批准设立的,专门从事金融期货.期权等金融衍生品交易与结算的公司制交易所.中金所由上海期货交易所.郑州商品交易所.大连商品交易所.上海证券交

「运维之美」技术周刊 ( 第 1 期 )

本文首发于:微信公众号「运维之美」,公众号 ID:Hi-Linux. ?「运维之美」是一个有情怀.有态度,专注于 Linux 运维相关技术文章分享的公众号.公众号致力于为广大运维工作者分享各类技术文章和发布最前沿的科技信息.公众号的核心理念是:分享,我们认为只有分享才能使我们的团体更强大.如果你想第一时间获取最新技术文章,欢迎关注我们! 公众号作者 Mike,一个月薪 3000 的杂工.从事 IT 相关工作 15+ 年,热衷于互联网技术领域,认同开源文化,对运维相关技术有自己独特的见解.很愿意将