其他分享
首页 > 其他分享> > 深圳技术大学第二届软件和信息技术大赛-题解报告

深圳技术大学第二届软件和信息技术大赛-题解报告

作者:互联网

写在前面

这次比赛出题人有三位

钱贵宁EFI

周家宝BCGH

徐嘉辉ADJ

由于本次比赛主要目的是为了选拔蓝桥杯的预备参赛队员,所以赛制上选择了大家可能比较陌生的OI赛制,所有提交只有赛后一次结算机会。考虑很多人第一次接触这个赛制,我们的数据上给出了很多组很小的数据,基本保证就算全部用最基础的暴力方法,都可以完成除了后2个压轴题的所有分数。题目分为5个填空5个编程题,从难度上说,ABC考察了对基础语法和数据结构知识的了解,DE正解分别要用BFS和数论,前三个编程题都是语法层面的考察,I题考察了异或的灵活运用,处于友好set或sort的算法也也能拿到所有分数。压轴题暴力能拿4分或8分,正解是莫比乌斯反应。从得分分布来看,区分度也基本符合预期。如果有兴趣了解比赛中题目的正解,可以继续看下去

A土豆摸鱼

首先考虑闰年的数量算出天数,根据5和7的最小公倍数得出周期判断即可。

#include<stdio.h>
int main(){
	int a,b,c;
	a=365*10+3+31*3+30*2+10+23;//总共有3839天 
	b=a/35;// 5和7的最小公倍数是35;以35天为周期,每个周期满足条件的星期三有2天 ;共109个周期 
	c=a%35;//多出的24天内满足条件的星期三有2天;
	printf("%d",b*2+2);
}

D黑白棋

这个题目正解要用状态压缩和BFS一起来解决问题。思路可以概括为广搜+map去重,map里存过程中的状态 ,用bfs遍历所有状态,得到需要的最短步数。这道题由于给出情况比较简单,观察后很容易直接输出来,不过正解代码还是发出来给大家参考。

#include<bits/stdc++.h>
using namespace std;
queue<string>q;
string a,b;
map<string,string>m;
void yy(int i,string ss){//上下换
    string sss=ss;
    char c;
    c=ss[i];
    ss[i]=ss[i+4];
    ss[i+4]=c;
    if(m.count(ss)==0){
        q.push(ss);
        char aa=49+i/4,bb=49+i%4,cc=50+i/4,dd=49+i%4;//这里的横竖坐标都是从0开始的,存进去要加1
        m[ss]=m[sss]+aa+bb+cc+dd;
    }
    return;
}
void xx(int i,string ss){//左右换
    string sss=ss;
    char c;
    c=ss[i];
    ss[i]=ss[i+1];
    ss[i+1]=c;
    if(m.count(ss)==0){
        q.push(ss);
        char aa=49+i/4,bb=49+i%4,cc=49+i/4,dd=50+i%4;
        m[ss]=m[sss]+aa+bb+cc+dd;
    }
    return;
}
//考虑四个方向会重复,所以只需考虑两个方向,这里是右和下。
void bfs(){
    q.push(a);
    m[a]="";
    while(q.empty()==false){
        string ss=q.front();
        for(int i=0;i<16;i++){
            if(i<12){//不是最后一行就和下面换
                yy(i,ss);
            }
            if(i%4!=3){//不是最后一列就和右边换
                xx(i,ss);    
            }
        }
        if(m.count(b)!=0){//出现目标序列
            cout<<m[b].size()/4<<endl;
            for(int j=0;j<m[b].size();j++){
                cout<<m[b][j];
                if(j%4==3)cout<<endl;//每输出四个换一行
            }
            return;
        }
        q.pop();
    }
    return;
}
int main(){
    for(int i=0;i<16;i++){
        char c;
        cin>>c;
        a+=c;
    }
    for(int i=0;i<16;i++){
        char c;
        cin>>c;
        b+=c;
    }
    bfs();
    return 0;
}

J我本来是签到题

这道题如果仅仅用暴力去解决只能通过1/6的数据点,稍加优化可以通过1/3.不过都不足以解决问题。

 正确做法是我们先用c数组预处理出每个数出现的次数,那么原问题变为求解

其中n表示最大的数。然后莫比乌斯反演转化一下

代码就是莫比乌斯反演的基本板子

#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define MAXN 50005
#define rgt register
int N, M, cnt[MAXN], mu[MAXN], p[MAXN], tot, v[MAXN];
LL s[MAXN];
LL ans(0);
int main(){
    scanf( "%d", &N ); for ( rgt int i = 1, x; i <= N; ++i ) scanf( "%d", &x ), ++cnt[x], M = max( M, x );
    N = M, mu[1] = 1;
    for ( rgt int i = 2; i <= N; ++i ){//线性筛出mu
        if ( !v[i] ) p[++tot] = i, mu[i] = -1;
        for ( rgt int j = 1; j <= tot && i * p[j] <= N; ++j ){
            v[i * p[j]] = 1;
            if ( i % p[j] == 0 ){ mu[i * p[j]] = 0; break; }
            else mu[i * p[j]] = -mu[i];
        }
    }
    for ( rgt int i = 1; i <= N; ++i )
        for ( rgt int j = i; j <= N; j += i )
            s[j] += 1ll * mu[i] * i;
    for ( rgt int T = 1; T <= N; ++T ){
        rgt LL cur(0);
        for ( rgt int i = 1, I = N / T; i <= I; ++i ) cur += 1ll * cnt[i * T] * i;//暴力求解
        ans += T * cur * cur * s[T];
    } printf( "%lld\n", ans );
    return 0;
}

持续更新中。。

Ans=\sum_{i=1}^n\sum_{j=1}^nlcm(i,j)\times c_i\times c_j

标签:string,第二届,ss,题解,49,大赛,int,正解,MAXN
来源: https://www.cnblogs.com/tscjj/p/14136622.html