山东协和学院-计算机学院第七届程序设计竞赛-题解

A.运气游戏(50 score)

思路:仔细阅读题面输出BU即可

代码:

BU

B.ACM赛制(100 score)

思路:本题有两个坑,①AC后还是有可能提交错误,②AC的时间可能会跨越本天,代码统计直到第一次AC前 非CE的个数cnt,因为比赛的开始时间为14点,有可能比到第二天才AC这道题目,需要判断第一次AC的时间是在14点之前还是之后,若在14点之后表示没有跨天,输出 (AC时的小时-14)*60+AC时的分钟+cnt*20 ,若在14点之前表示过了一天, 输出600+AC时的小时*60+AC时的分钟+cnt*20。

代码:

void solve(){
    ll n;cin>>n;
    ll cnt=0;
    for (ll i = 1; i <= n; i++)
    {
        ll o,p;string c;cin>>o>>p>>c;
        if(c=="AC"){
            if(o>=14){
                cout<<(o-14)*60+p+cnt*20;
            }else{
                cout<<600+o*60+p+cnt*20;
            }
            return;
        }
        if(c!="CE") cnt++;
    }
}

C.字符操作(100 score)

思路:统计0的个数 若不为0 则结果为是,考虑两种情况,①只有0的情况,直接符合条件输出是,②有0有1,那我可以在0和1的分界线中一直插入0,直到0的个数大于1的个数。所以当字符串中有0则输出是,没有0则输出否。

代码:

void solve(){
    ll n;cin>>n;
    string s;cin>>s;
    ll l=0,r=0;
    for (ll i = 0; i < s.size(); i++)
    {
        if(s[i]=='0') l++;
        else r++;
    }
    if(l!=0) cout<<"是\n";
    else cout<<"否\n";
     
}

D.重复筛选(100 score)

算法:哈希表

思路:先用map统计每个数字出现的个数,然后遍历数组,查询和当前数字可以组成完美字符的个数,也就是统计当前数+k和-k的个数,假设1 3可以组成完美字符,当遍历到1的时候1和3被统计过一次,遍历到3的时候1也被统计了,所以最终结果ans除以2即可。

代码:

void solve(){
    ll n,m;cin>>n>>m;
    for (ll i = 1; i <= n; i++)
    {
        cin>>a[i];
        mp[a[i]]++;
    }
    ll ans=0;
    for (ll i = 1; i <= n; i++)
    {
        ans+=mp[a[i]+m];
        ans+=mp[a[i]-m];
    }
    cout<<ans/2;
     
}

E.只要不扔垃圾,我什么都愿意做(150 score)

算法:栈和队列

思路:模拟题,用STL中队列和栈,根据题意模拟即可。

代码:

ll a[Q];
void solve(){
    ll t,k,n;cin>>t>>k>>n;
    for (ll i = 1; i <= n; i++)
    {
        cin>>a[i];
    }
    if(t*k>n){
        cout<<"<censored>\n";
        return;
    }
    queue<ll> q;
    for (ll i = 1; i <= t*k; i++){
        q.push(a[i]);
    }
    while (q.size())
    {
        stack<ll> st;
        for (ll i = 0; i < t; i++){
            st.push(q.front());q.pop();
        }
        for (ll i = 0; i < t; i++){
            cout<<st.top()<<" ";st.pop();
        }
        if(q.size()){
            for (ll i = 0; i < t; i++){
                q.push(q.front());q.pop();
            }
        }
    }
     
     
     
}

F.最长对称子串(100 score)

算法:双指针

思路:遍历每一个位置,然后从每一个位置出发,记录双指针往两边跑,当左指针等于右指针时,左指针往左移右指针往右移,直到左右指针对应位置上的元素不同,记录当前左右指针之间的个数。因为ABA和AA都算对称,所以要跑两遍双指针,当前位置为i时候, 一次双指针为 i-1 和 i+1,另一次为i 和 i+1。

代码:

void solve(){
    string s;
    getline(cin,s);
    ll l,r;
    ll ans=1;
    for (ll i = 0; i < s.size(); i++)
    {
        l=i-1,r=i+1;
        ll cnt=1;
        while(l>=0 and r<s.size()){
            if(s[l]==s[r]) cnt+=2,ans=max(ans,cnt);
            else break;
            l--,r++;
        }
        l=i,r=i+1;
        cnt=0;
        while(l>=0 and r<s.size()){
            if(s[l]==s[r]) cnt+=2,ans=max(ans,cnt);
            else break;
            l--,r++;
        }
    }
    cout<<ans;
}

G.桌游(150 score)

算法:单调队列

思路:先排序,然后维护一个队尾减队头大小 小于k的队列,并且队列中的相邻元素大小差距小于等于1,记录队列的个数即为答案。

代码:

#include<bits/stdc++.h>
#define endl '\n'
using namespace std;
using ll = long long;
const ll Q = 2e5 + 9;
const ll MOD = 1e9+7;
ll a[Q];ll ans=0;
void solve(){
    ll n,m;cin>>n>>m;
    ans=0;
    for (ll i = 1; i <= n; i++)
    {
        cin>>a[i];
    }
    sort(a+1,a+1+n);
    queue<ll> q;
    for (ll i = 1; i <= n; i++)
    {
        while(q.size() and !(q.back()==a[i] or q.back()==a[i]-1)) q.pop();

        q.push(a[i]);
        while(q.size() and q.back()-q.front()+1 > m){
            q.pop();
        }
        ans=max(ans,(ll)q.size());
    }
    
    cout<<ans<<"\n";
}
int main()
{
    ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
    ll _ = 1;cin>>_;
    while(_--)solve();
    return 0;
}

H.节水(100 score)

算法:前缀和

思路:先让用时少的人先接水,这样平均用时就短了,也就是先排序,然后求每个元素和它前面所有元素的和,输出即可。

代码:

void solve(){
    ll n;cin>>n;
    for (ll i = 1; i <= n; i++)
    {
        cin>>a[i];
    }
    sort(a+1,a+1+n);
    for (ll i = 1; i <= n; i++)
    {
        a[i]+=a[i-1];
        cout<<a[i]<<" ";
    }
}

I.贪心(100 score)

算法:深度优先搜索

思路:DFS搜索每个元素选还是不选,l和r变量记录选和不选的和,搜索结束后更新最优答案。

代码:

#include<bits/stdc++.h>
#define endl '\n'
using namespace std;
using ll = long long;
const ll Q = 2e5 + 9;
const ll MOD = 1e9+7;
ll a[Q];ll n;ll ans=MOD;
void dfs(ll l,ll r,ll cnt){
    if(cnt>n){
        ans=min(ans,abs(l-r));
        return;
    }
    dfs(l+a[cnt],r,cnt+1);
    dfs(l,r+a[cnt],cnt+1);
}
void solve(){
    cin>>n;
    for (ll i = 1; i <= n; i++)
    {
        cin>>a[i];
    }
    dfs(0,0,1);
    cout<<ans;
}
int main()
{
    ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
    ll _ = 1;//cin>>_;
    while(_--)solve();
    return 0;
}

J.急着回家的洛琪希(200 score)

算法:二分搜索

思路:二分搜索灯笼的功率,每次检查在此功率下是否满足条件,第一个或第二个灯笼同时照亮起点和终点,或者,两个灯笼之间的距离小于功率的两倍且两个灯笼共同照亮起点和终点 时候符合条件。

代码:

#include<bits/stdc++.h>
#define endl '\n'
using namespace std;
using ll = long long;
const ll Q = 2e5 + 9;
const ll MOD = 1e9+7;
ll x,y;ll x1;ll y3;ll x2;ll y2;
double jl(ll o,ll p,ll o1,ll p1){
    return sqrtl((o1-o)*(o1-o)+(p1-p)*(p1-p));
}
bool check(double t){
    if(jl(x1,y3,0,0)<=t and jl(x,y,x1,y3)<=t){
        return true;
    }
    if(jl(x2,y2,0,0)<=t and jl(x,y,x2,y2)<=t){
        return true;
    }
    if(jl(x1,y3,x2,y2)<=t*2 and (jl(x,y,x1,y3)<=t or jl(x,y,x2,y2)<=t) and (jl(0,0,x1,y3)<=t or jl(0,0,x2,y2)<=t)){
        return true;
    }
    return false;
}

void solve(){
    cin>>x>>y;
    cin>>x1>>y3;
    cin>>x2>>y2;
    double ans=0;
    double l=0,r=MOD;
    while(r-l>=0.0000001){
        double mid=(l+r)/2;
        if(check(mid)){
            ans=mid;
            r=mid;
        }else{
            l=mid;
        }
    }
    printf("%.6lf\n",ans);
}
int main()
{
    ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
    ll _ = 1;cin>>_;
    while(_--)solve();
    return 0;
}

K.小乐想打cs(100 score)

算法:前缀和 预处理

思路:提前计算出1到100000的每个元素的数位和,然后求当前元素和之前所有元素的和是多少 ,并储存在数组中,每次询问时输出对应答案即可。

代码:

#include<bits/stdc++.h>
#define endl '\n'
using namespace std;
using ll = long long;
const ll Q = 2e5 + 9;
const ll MOD = 1e9+7;
ll a[Q];ll n;
void solve(){
    ll n;cin>>n;
    cout<<a[n]<<"\n";
}
int main()
{
    ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
    
    for (ll i = 1; i <= Q; i++)
    {
        ll now=0;
        ll cnt=i;
        while(cnt){
            now+=cnt%10;
            cnt/=10;
        }
        a[i]=a[i-1]+now;
    }
    
    
    ll _ = 1;cin>>_;
    while(_--)solve();
    return 0;
}

L.独特的记忆(50 score)

思路:循环枚举找出满足 i+j=x 和 i-j=y的i和j两个元素 输出i和j即可。

代码:

void solve(){
    ll x,y;cin>>x>>y;
    for (ll i = -1000; i <= 1000; i++)
    {
        for (ll j = -1000; j < 1000; j++)
        {
            if(i+j==x and i-j==y){
                cout<<i<<" "<<j<<"\n";
                return;
            }
        }
         
    }
    cout<<-1;
}

M.Trees and XOR Queries Again(50 score)

思路:先判断当前是否符合条件 符合则输出0,然后找出两个相邻的字符相同的位置输出当前的位置即可。 因为string元素从0开始记录所以当前位置就是下标+1。

代码:

#include<bits/stdc++.h>
#define endl '\n'
using namespace std;
using ll = long long;
const ll Q = 2e5 + 9;
const ll MOD = 1e9+7;
ll a[Q];ll n;
void solve(){
    string s;cin>>s;
    if(s[0]==s[s.size()-1]){
        cout<<0<<"\n";
        return;
    }
    for (ll i = 0; i < s.size(); i++)
    {
        if(s[i]==s[i+1]) {
            cout<<i+1<<"\n";
            return;
        }
    }
    cout<<-1<<"\n";
}
int main()
{
    ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
    ll _ = 1;cin>>_;
    while(_--)solve();
    return 0;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值