2018浙江第十五届ACM省赛题解(待补完)

题目链接 http://acm.zju.edu.cn/onlinejudge/showContestProblems.do?contestId=378

没有solution的题目待补

A

暴力

无技巧

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int debug_num=0;
#define debug cout<<"debug "<<++debug_num<<" :"

const int inf=2e9+10;

const int maxn=1e5+10;

int a[maxn];

int main()
{
    //freopen("in.txt","r",stdin);
    ios::sync_with_stdio(false);
    int t;
    cin>>t;
    while(t--)
    {
        int n;
        cin>>n;
        for(int i=0;i<n;++i)
            cin>>a[i];
        int maxx=a[0];
        int ans=0;
        for(int i=1;i<n;++i){
            if(a[i]>maxx){
                maxx=a[i];
                ans=i;
            }
        }
        if(ans==0||ans==n-1) cout<<"No"<<endl;
        else{
            int flag=1;
            for(int i=0;i<ans;++i){
                if(a[i]>=a[i+1]) {
                    cout<<"No"<<endl;
                    flag=0;
                    break;
                }
            }
            if(flag==0) continue;
            for(int i=ans;i<n-1;++i){
                if(a[i]<=a[i+1]) {
                    cout<<"No"<<endl;
                    flag=0;
                    break;
                }
            }
            if(flag) cout<<"Yes"<<endl;
        }
    }
    return 0;
}

B

做差,用数组做桶计数

注意做个差值shift,使得下标在合适区间

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int debug_num=0;
#define debug cout<<"debug "<<++debug_num<<" :"

const int maxn=1e5+10;


int n;

int a[maxn];
int b[maxn];
int c[maxn*4];

int main()
{
    //freopen("in.txt","r",stdin);
    ios::sync_with_stdio(false);
    int t;
    cin>>t;
    while(t--)
    {
        memset(c,0,sizeof(c));
        int n;
        cin>>n;
        for(int i=0;i<n;++i){
            cin>>a[i];
        }
        for(int i=0;i<n;++i){
            cin>>b[i];
        }
        for(int i=0;i<n;++i){
            c[a[i]+(int)2e5-b[i]]++;
        }
        sort(c,c+4*maxn);
        cout<<c[4*maxn-1]<<endl;
    }
    return 0;
}

C

D

E

F

1inailogpai ∑ 1 ≤ i ≤ n ⌊ a i ⌈ log p ⁡ a i ⌉ ⌋

观察上式,当p最小,a最大时,分母取值最大,为30。

对a数组进行sort,之后可将a分段,最多30段,每一段都除以相同的数值

如何分段呢?二分

分好段后,需要快速求得段内除以这个数的下取整和值

对sort后的a数组预处理前缀和即可,由于除数最大30,要开30维

时间复杂度 O(mlognlogamaxp+nlogn) O ( m ∗ l o g n ∗ l o g p a m a x + n l o g n ) 其中 m m 为查询次数,logn为每一次二分的复杂度, logamaxp l o g p a m a x 为二分次数。 nlogn n l o g n 为一次排序的复杂度

数据量超过1e6使用快读是个好习惯

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int debug_num=0;
#define debug cout<<"debug "<<++debug_num<<" :"
const int mod=1e9;

const int maxn=5e5+10;

int read()
{
    char ch='*';
    while(!isdigit(ch=getchar()));//不是数字读掉
    int num=ch-'0';
    while(isdigit(ch=getchar())) num=num*10+ch-'0';
    return num;
}

int pre[31][maxn];
int a[maxn];
int p[maxn];
int n,m;

void init()
{
    //求出pre /1,/2,/30的前缀和
    //memset(pre,0,sizeof(pre));
    for(int chu=1;chu<=30;++chu){
        pre[chu][0]=0;
    }
    for(int chu=1;chu<=30;++chu){
        for(int i=1;i<=n;++i){
            pre[chu][i]=(pre[chu][i-1]+a[i]/chu)%mod;
        }
    }
}

int main()
{
    //freopen("in.txt","r",stdin);
    int t;
    scanf("%d",&t);
    while(t--)
    {
        //cin>>n>>m;//n个数字   m个p
        //cout<<n<<" "<<m<<endl;
        scanf("%d %d",&n,&m);
        for(int i=1;i<=n;++i) a[i]=read();
        for(int i=1;i<=m;++i) p[i]=read();
//        for(int i=1;i<=n;++i) cin>>a[i];
//        for(int i=1;i<=m;++i) cin>>p[i];
        //debug<<"*****************"<<endl;
        ll ans=0;
        sort(a+1,a+1+n);
        init();
//        for(int i=1;i<=n;++i){
//            cout<<a[i]<<" ";
//        }
//        cout<<endl;
        for(int i=1;i<=m;++i){//对于每个询问  log 的底数为p[i]
            //debug<<"第"<<i<<"次询问:"<<endl;
            ll sum=0;
            //除1的在 1~p 之间
            //除2的在p+1 ~p^2 之间
            //...
            //除30的在p^29+1 ~ p^30
            ll now_p=p[i];
            int id1=1;//id1左边界 id2右边界
            int id2;
            int chu=1;
            while(1){
                id2=upper_bound(a+1+(id1-1),a+1+n,now_p)-a-1;//返回小于等于now_p的最后一个数
                //debug<<"id1 id2 now_p chu   "<<id1<<" "<<id2<<" "<<now_p<<" "<<chu<<endl;
                if(id2>=id1) sum=(sum+pre[chu][id2]-pre[chu][id1-1]+mod)%mod;//,cout<<"***"<<pre[chu][id2]-pre[chu][id1-1]<<endl
                id1=id2+1;//下一次的左边界一定是上一次右边界的下一个
                now_p=now_p*p[i];
                chu++;
                if(id2>=n) break;
            }
            ans=(ans+((i*sum)%mod))%mod;
        }
        printf("%lld\n",ans);
    }
    return 0;
}

G

H

I

一定可以产生 n(n1)/2 n ( n − 1 ) / 2 个点

策略如下图,分情况讨论即可

img

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int debug_num=0;
#define debug cout<<"debug "<<++debug_num<<" :"


int main()
{
    //freopen("in.txt","r",stdin);
    ios::sync_with_stdio(false);
    int t;
    cin>>t;
    while(t--)
    {
        int n;
        cin>>n;
        if(n%2==0){
            for(int i=0;i<=n-3;++i){
                if(i%2==0){
                    cout<<i<<" "<<2*n-2-i-1<<" ";
                }
                else cout<<i<<" "<<2*n-2-i+1<<" ";
            }
            cout<<n-2<<" "<<n<<" ";
            cout<<n-1<<" "<<2*n-1<<endl;
        }
        else{
            //奇数
            //0~n-1
            for(int i=0;i<=n-2;++i){
                if(i%2==0){
                    cout<<i<<" "<<2*n-2-i-1<<" ";
                }
                else cout<<i<<" "<<2*n-2-i+1<<" ";
            }
            cout<<n-1<<" "<<2*n-1<<endl;
        }
    }
    return 0;
}

J

贪心

考虑只要能将所有宝贝数量恰好分半到两个组即可。因为一旦这件事能完成,男女性别一定不是问题,题目说明可以有组为空

下面考虑如何将宝贝恰好分半

首先当 n%4==1||2 n % 4 == 1 | | 2 的 时候一定无解

n%4==0 n % 4 == 0 时,很好分两半,即首位依次配对

n%4==3 n % 4 == 3 时,对于前面一样做,对于最后三个人,价值分别为n-2,n-1,n

将n-2和n两个人分到有(n-1)/2的那组去

将(n-1)/2换到另外一组,n-1也放到该组即可

if写了100多行 太丑了

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int debug_num=0;
#define debug cout<<"debug "<<++debug_num<<" :"

const int maxn=1e5+10;

char ans[maxn];

char s[maxn];

int main()
{
    //freopen("in.txt","r",stdin);
    ios::sync_with_stdio(false);
    int t;
    cin>>t;
    while(t--)
    {
        memset(ans,0,sizeof(ans));
        memset(s,0,sizeof(s));
        int n;
        cin>>n;
        for(int i=1;i<=n;++i){
            cin>>s[i];
        }
        if(n%4==1||n%4==2){
            cout<<-1<<endl;
            continue;
        }
        if(n%4==0){
            for(int i=1;i<=n;++i){
                if(i%4==0||i%4==1){
                    if(s[i]=='1'){
                        ans[i]='3';
                    }
                    else{
                        ans[i]='1';
                    }
                }
                else{
                    if(s[i]=='1'){
                        ans[i]='4';
                    }
                    else{
                        ans[i]='2';
                    }
                }
            }
            for(int i=1;i<=n;++i){
                cout<<ans[i];
            }
            cout<<endl;
        }
        else{
            if(n<4){
                //cout<<n<<"***"<<endl;
                if(s[1]=='1') ans[1]='3';
                else ans[1]='1';
                if(s[2]=='1') ans[2]='3';
                else ans[2]='1';
                if(s[3]=='1') ans[3]='4';
                else ans[3]='2';
                                for(int i=1;i<=n;++i){
                                    cout<<ans[i];
                            }
                            cout<<endl;
            }
            else{
            int ahu=0;
            for(int i=1;i<=n-3;++i){
                if(i==(n-1)/2) ahu=(n-1)/2;
                if(i%4==0||i%4==1){
                    if(s[i]=='1'){
                        ans[i]='3';
                    }
                    else{
                        ans[i]='1';
                    }
                }
                else{
                    if(s[i]=='1'){
                        ans[i]='4';
                    }
                    else{
                        ans[i]='2';
                    }
                }
            }
            //ahu是特殊元素
            if(ahu%4==0||ahu%4==1){//这种情况ahu现在被放在1,3 ,将其改为2,4

                if(s[ahu]=='1') ans[ahu]='4';
                else ans[ahu]='2';
                if(s[n-1]=='1') ans[n-1]='4';
                else ans[n-1]='2';


                if(s[n-2]=='1') ans[n-2]='3';
                else ans[n-2]='1';
                if(s[n]=='1') ans[n]='3';
                else ans[n]='1';
            }
            else{//这种情况ahu现在被放在2,4,将其改为1,3
                if(s[ahu]=='1') ans[ahu]='3';
                else ans[ahu]='1';
                if(s[n-1]=='1') ans[n-1]='3';
                else ans[n-1]='1';


                if(s[n-2]=='1') ans[n-2]='4';
                else ans[n-2]='2';
                if(s[n]=='1') ans[n]='4';
                else ans[n]='2';
            }
            for(int i=1;i<=n;++i){
                cout<<ans[i];
            }
            cout<<endl;
            }
        }
    }
    return 0;
}


K

L

水题

无技巧

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int debug_num=0;
#define debug cout<<"debug "<<++debug_num<<" :"

const int maxn=200;

struct node{
    string s;
    ll v;
}no[maxn];

bool cmp(node a,node b)
{
    if(a.v==b.v) return a.s<b.s;
    return a.v>b.v;
}

int main()
{
    //freopen("in.txt","r",stdin);
    ios::sync_with_stdio(false);
    int t;
    cin>>t;
    while(t--)
    {
        int n,m;
        cin>>n>>m;
        for(int i=0;i<n;++i){
            cin>>no[i].s>>no[i].v;
        }
        sort(no,no+n,cmp);
//        for(int i=0;i<n;++i){
//            cout<<no[i].s<<" "<<no[i].v<<endl;
//        }
        ll sum=0;
        ll tp=m;
        for(int i=0;i<m;++i){
            //cout<<no[i].s<<" ";
            sum+=tp*no[i].v;
            tp--;
        }
        cout<<sum<<" ";
        for(int i=0;i<m;++i){
            if(i==m-1) cout<<no[i].s<<endl;
            else cout<<no[i].s<<" ";
        }

    }
    return 0;
}

M

水题

无技巧

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int debug_num=0;
#define debug cout<<"debug "<<++debug_num<<" :"



int main()
{
    //freopen("in.txt","r",stdin);
    ios::sync_with_stdio(false);
    int t;
    cin>>t;
    while(t--)
    {
    int n,b;
    cin>>n>>b;
    int flag=0;
    for(int i=0;i<n;++i){
        int tp;
        cin>>tp;
        if((tp+b)%7==0){
            flag=1;
        }
    }
    if(flag){
        cout<<"Yes"<<endl;
    }
    else cout<<"No"<<endl;
    }
    return 0;
}

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值