2018 Multi-University Training Contest 1

本文精选了多个ACM竞赛中的经典题目解决方案,包括数学运算、字符串处理、数据结构操作及算法设计等内容,通过具体示例展示了高效算法实现技巧。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

hdu这边做得好像更惨一点,感觉苟进rk10基本没希望啊。
A
签到。

#include <bits/stdc++.h>
using namespace std;
int main(){
    int T;
    scanf("%d",&T);
    while(T--){
        int n;
        scanf("%d",&n);
        if(n%3==0){
            printf("%lld\n",1ll*n*n*n/27);
        }
        else if(n%4==0){
            printf("%lld\n",1ll*n*n*n/32);
        }
        else printf("-1\n");
    }
}

B
这题神似洗衣服啊,还好想起了时光倒流大法。

#include <bits/stdc++.h>
using namespace std;
int T;
int ans;
int n;
char s[100003];
int l[100003],r[100003];
void gao(char s[],int id){
    int tmp=0;
    l[id]=0;
    for(int i=0;s[i];i++){
        if(s[i]=='(')tmp++;
        else {
            if(tmp>0){
                tmp--;
                ans++;
            }
            else {
                l[id]++;
            }
        }
    }
    r[id]=tmp;
}
struct que{
    int c,add;
}u[100003],d[100003];
int utot,dtot;
bool cmp1(que a,que b){
    return a.c<b.c;
}
bool check(int tmp1,int tmp2){
    for(int i=1;i<=utot;i++){
        if(tmp1<u[i].c){
            return false;
        }
        tmp1+=u[i].add;
    }
    for(int i=1;i<=dtot;i++){
        if(tmp2<d[i].c){
            return false;
        }
        tmp2+=d[i].add;
    }
    return true;
}
int main(){
    scanf("%d",&T);
    while(T--){
        scanf("%d",&n);
        ans=0;
        int sum=0;
        int sumr=0;
        utot=0;
        dtot=0;
        for(int i=1;i<=n;i++){
            scanf("%s",s);
            gao(s,i);
            sum+=l[i];
            sumr+=r[i];
            if(l[i]==r[i]){
                ++utot;
                u[utot]=(que){l[i],r[i]-l[i]};
                ++dtot;
                d[dtot]=(que){r[i],l[i]-r[i]};
            }
            else if(l[i]<r[i]){
                ++utot;
                u[utot]=(que){l[i],r[i]-l[i]};
            }
            else {
                ++dtot;
                d[dtot]=(que){r[i],l[i]-r[i]};
            }
        }
        sort(u+1,u+1+utot,cmp1);
        sort(d+1,d+1+dtot,cmp1);
        int le=0,ri=min(sum,sumr),tag=-1;
        while(1){
            if(ri-le<=1){
                if(check(sum-ri,sumr-ri))tag=ri;
                else tag=le;
                break;
            }
            int mid=(le+ri)/2;
            if(check(sum-mid,sumr-mid))le=mid;
            else ri=mid;
        }
        printf("%d\n",(ans+tag)*2);
    }
}

C
签到。

#include <bits/stdc++.h>
using namespace std;
struct node{
    int x,y,id;
}rec[3003];
bool operator<(const node& a,const node& b){
    if(a.x==b.x)return a.y<b.y;
    return a.x<b.x;
}
int main(){
    int T;
    cin>>T;
    while(T--){
        int n;
    cin>>n;
        for(int i=1;i<=3*n;i++){
            cin>>rec[i].x>>rec[i].y;
            rec[i].id=i;
        }
        sort(rec+1,rec+1+3*n);
        for(int i=1;i<=n;i++){
            for(int j=1;j<=3;j++){
                printf("%d%c",rec[(i-1)*3+j].id,j==3?'\n':' ');
            }
        }
    }
}

D
按题意模拟即可。

#include <bits/stdc++.h>
using namespace std;
int ans[100003];
struct que{
    int l,r;
}rec[100003];
que a[100003];
set<int>s;
int tot;
int n,m;
bool operator<(const que& a,const que& b){
    if(a.l==b.l)return a.r>b.r;
    return a.l<b.l;
}
int main(){
    int T;
    scanf("%d",&T);
    while(T--){
        scanf("%d%d",&n,&m);
        for(int i=1;i<=m;i++){
            scanf("%d%d",&a[i].l,&a[i].r);
        }
        tot=0;
        sort(a+1,a+1+m);
        for(int i=1;i<=m;i++){
            if(tot!=0&&a[i].r<=rec[tot].r)continue;
            rec[++tot]=a[i];
        }
        s.clear();
        rec[0].l=1,rec[0].r=0;
        for(int i=1;i<=n;i++)ans[i]=1;
        for(int i=1;i<=n;i++)s.insert(i);
        for(int i=1;i<=tot;i++){
            if(rec[i].l<=rec[i-1].r){
                for(int j=rec[i-1].l;j<rec[i].l;j++)s.insert(ans[j]);
                for(int j=rec[i-1].r+1;j<=rec[i].r;j++){
                    auto it=s.begin();
                    ans[j]=*it;
                    s.erase(it);
                }
            }
            else {
                for(int j=rec[i-1].l;j<=rec[i-1].r;j++)s.insert(ans[j]);
                for(int j=rec[i].l;j<=rec[i].r;j++){
                    auto it=s.begin();
                    ans[j]=*it;
                    //cout<<j<<' '<<*it<<endl;
                    s.erase(it);
                }
            }
        }
        for(int i=1;i<=n;i++)printf("%d%c",ans[i],i==n?'\n':' ');
    }
}

G
倍增统计一下。

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const ll mod=1e9+7;

ll pow2[60],pow2num[60],pow2sum[60];
int t;
ll n;

void init(){
    pow2[0]=1;
    pow2num[0]=1;
    pow2sum[0]=1;
    for(int i=1; i<=59; i++){
        pow2[i]=pow2[i-1]*2;
        pow2num[i]=pow2num[i-1]*2+1;
        pow2sum[i]=(pow2sum[i-1]*2+(pow2[i-1]%mod)*((pow2num[i-1]+2)%mod))%mod;
        //cout<<i<<" : "<<pow2[i]<<" "<<pow2num[i]<<" "<<pow2sum[i]<<endl;
    }
    return;
}

ll getans(ll n){
    ll num=1,w=0,ans=1;
    for(int i=59; i>=0; i--){
        if(num+pow2num[i]<=n){
            //ans=(ans+pow2sum[i]+((pow2num[i]%mod)*(w%mod)%mod))%mod;
            //cout<<ans<<endl;
            ans=(ans+pow2sum[i])%mod;
            //cout<<ans<<" "<<w<<" ";
            ans=(ans+(pow2num[i]%mod)*(w%mod)%mod)%mod;
            //cout<<ans<<endl;
            num+=pow2num[i];
            w+=(1ll<<i);
        }
    }
    ans=(ans+((n-num)%mod)*((w+1)%mod)%mod)%mod;
    return ans;
}

int main(){
    init();
    scanf("%d",&t);
    while(t--){
        scanf("%lld",&n);
        ll ans=getans(n);
        printf("%lld\n",ans);
    }
    return 0;
}

H
手动多重积分,发现可以建个树树dp一下。建树的过程写的有点搓,但是过了。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod=1e9+7;
char buf[30000003];
int rdp=0;
inline int read(){
    int ret=0;
    while(buf[rdp]>='0'&&buf[rdp]<='9'){
        ret*=10;
        ret+=buf[rdp++]-'0';
    }
    rdp++;
    return ret;
}
int lo[1000003];
int a[1000003];
int f[1000003][22];
int lc[1000003];
int rc[1000003];
int deg[1000003];
int fa[1000003];
ll d1[1000003];
ll d2[1000003];
int siz[1000003];
void rmq_init(int n){
    for(int j=1;(1<<j)<=n;j++){
        for(int i=1;i+(1<<j)-1<=n;i++){
            int l=f[i][j-1];
            int r=f[i+(1<<(j-1))][j-1];
            if(a[l]>=a[r])f[i][j]=l;
            else f[i][j]=r;
        }
    }
}
int rmq(int l,int r){
    int j=lo[r-l+1];
    int le=f[l][j];
    int ri=f[r-(1<<j)+1][j];
    if(a[le]>=a[ri])return le;
    return ri;
}
ll power(ll n,ll p){
    ll ans=1;
    ll base=n;
    while(p){
        if(p&1){
            ans=ans*base%mod;
        }
        base=base*base%mod;
        p>>=1;
    }
    return ans;
}
ll getinv(ll n){
    return power(n,mod-2);
}
void build(int u,int l,int r){
    if(l>r)return ;
    int v=rmq(l,r);
    if(u>v){lc[u]=v;fa[v]=u;deg[u]++;}
    else {rc[u]=v;fa[v]=u;deg[u]++;}
    build(v,l,v-1);
    build(v,v+1,r);
}

ll inv[1000003];

void solve(int u){
    if(u==-1)return ;
    siz[u]=1;
    d1[u]=1;
    d2[u]=0;
    if(lc[u]!=-1){
        int v=lc[u];
        siz[u]+=siz[v];
        d1[u]=d1[u]*d1[v]%mod;
        if(rc[u]==-1)d2[u]=(d2[u]+d2[v]*inv[siz[v]+1])%mod;
        else d2[u]=(d2[u]+d2[v]*inv[siz[v]+1]%mod*d1[rc[u]])%mod;
    }
    if(rc[u]!=-1){
        int v=rc[u];
        siz[u]+=siz[v];
        d1[u]=d1[u]*d1[v]%mod;
        if(lc[u]==-1)d2[u]=(d2[u]+d2[v]*inv[siz[v]+1])%mod;
        else d2[u]=(d2[u]+d2[v]*inv[siz[v]+1]%mod*d1[lc[u]])%mod;
    }
    d2[u]=(d2[u]+d1[u])%mod;
    d1[u]=d1[u]*inv[siz[u]]%mod;
}
int que[1000003];
int head,tail;
int main(){
    inv[0]=1;
    for(int i=1;i<=1000001;i++){
        lo[i]=31-__builtin_clz(i);
        inv[i]=getinv(i);
    }
    fread(buf,1,30000000,stdin);
    int T;
    T=read();
    while(T--){
        int n;
        n=read();
        for(int i=1;i<=n;i++){
            a[i]=read();
            f[i][0]=i;
            lc[i]=rc[i]=-1;
            deg[i]=0;
        }
        rmq_init(n);
        int rt=rmq(1,n);
        fa[rt]=0;
        build(rt,1,rt-1);
        build(rt,rt+1,n);
        head=1,tail=0;
        for(int i=1;i<=n;i++)if(!deg[i])que[++tail]=i;
        for(int i=1;i<=n;i++){
            solve(que[head]);
            deg[fa[que[head]]]--;
            if(!deg[fa[que[head]]])que[++tail]=fa[que[head]];
            head++;
        }
        printf("%lld\n",d2[rt]*inv[n+1]%mod);
    }
}

K
签到。

#include <bits/stdc++.h>
using namespace std;

int t,a,b,x,y;
char str[10];
//UTC+8
//UTC+14
//UTC+8.1
//UTC-14.3
//01234567
void init (){
    int l=strlen (str);
    if (l==5){
        x=(str[4]-'0');
        y=0;
    }
    else if (l==6){
        x=(str[4]-'0')*10+(str[5]-'0');
        y=0;
    }
    else if (l==7){
        x=(str[4]-'0');
        y=(str[6]-'0');
    }
    else{
        x=(str[4]-'0')*10+(str[5]-'0');
        y=(str[7]-'0');
    }
    if (str[3]=='-'){
        x=-x;
        y=10-y;x--;
    }
    x+=24;
    // cout<<x<<' '<<y<<endl;
}

void work(){
    a+=(x-8);
    a%=24;
    b+=y*6;
    if (b>=60){
        b-=60;
        a++;
        a%=24;
    }
    printf("%02d:%02d\n",a,b);
}

int main (){
    cin>>t;
    while (t--){
        scanf ("%d%d",&a,&b);
        scanf ("%s",str);
        init ();
        work ();
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值