新oj压力测试及水题娱乐赛(水水更健康)---题解

比赛题目很简单嘛,大一的随便4题吧,大二的随便6题吧,感觉大二的普遍菜一点?比赛连接在这里点击打开链接

A:这个随机数是67,自己从1到100一个数一个数试也没有问题的啊,就第67就AC了

B:两层循环套着找一下就可以了,输出的时候找到一个就输一个就可以了,不要担心没有输完这种东西,文件输入输出,另外注意一下格式问题就可以了

#include <bits/stdc++.h>
 
using namespace std;
 
int main(){
    int n,m;
    char mp[25][25];
    while(~scanf("%d%d",&n,&m)){
        int cot = 0;
        for(int i = 0;i < n;i++){
            for(int j = 0;j < m;j++){
                cin>>mp[i][j];
                if(mp[i][j] == '@'&&cot != 0) PRintf(" (%d,%d)",i,j),cot++;
                if(mp[i][j] == '@'&&cot == 0) printf("(%d,%d)",i,j),cot++;
            }
        }
        if(cot == 0) puts("-1");
        else puts("");
    }
    return 0;
}

C:随便筛一下素数就可以了,0的时候输出sum就可以了

#include <bits/stdc++.h>
 
using namespace std;
 
bool is_prime(int n){
    for(int i = 2;i * i <= n;i++)
        if(n % i == 0) return false;
    return true;
}
 
int main(){
    int n;
    int sum = 0;
    while(~scanf("%d",&n)){
        if(n == 0) {printf("%d\n",sum);break;}
        else if(n == 1) continue;
        else if(is_prime(n)) sum+=n;
    }
    return 0;
}

D:判断是不是2的幂的时候要注意一下,这里使用位运算,i&(i-1)具体为什么这样写呢,大家可以去分别输出i和i-1的二进制值,然后两个做且运算,就可以明白为什么这样写了,预处理一下前缀和就可以了

#include <bits/stdc++.h>
 
using namespace std;
typedef long long ll;
 
int main(){
    int n,a[1005];
    ll sum[1005];
    memset(a,0,sizeof(a));
    memset(sum,0,sizeof(sum));
    for(int i = 1;i < 1005;i++){
        if((i&(i-1)) == 0) a[i] = i;
        else a[i] = -i;
    }
    for(int i = 1;i < 1005;i++)
        sum[i] = sum[i-1]+a[i];
    while(~scanf("%d",&n)){
        printf("%d\n",sum[n]);
    }
    return 0;
}


E:因为n <= 10,所以两层循环套一下就可以了,复杂度最坏也就1e6,要理解韩信点兵是什么意思,时间上就是给你总人数对某个数求余,然后剩下多少个人,循环去找一下,满足所有的条件才行,即第二层循环找完才可以,由于是找最小,找到了后我们直接输出就可以了

#include <bits/stdc++.h>
 
using namespace std;
 
int main(){
    int n,l[100005],r[100005];
    while(~scanf("%d",&n)){
        memset(l,0,sizeof(l));
        memset(r,0,sizeof(r));
        for(int i = 0;i < n;i++)
            scanf("%d%d",&l[i],&r[i]);
        int i,j;
        for(i = 1;i <= 100000;i++){
            for(j = 0;j < n;j++){
                if(i % l[j] != r[j]) break;
            }
            if(j == n) {printf("%d\n",i);break;}
        }
    }
    return 0;
}
 

F:一个模拟题,输入比较恶心,但是还是比较好模拟的,具体看代码(这是一份比较短的代码):

#include<stdio.h>
#include<string.h>
int main()
{
    char a,b,c,d,e[10],z[5],x[5],f,g;
    int q,w,r,n,m;
   while (scanf("%s %c,%c",z,&a,&b)!=EOF)
    { gets(z);
    scanf("%s %c %d;",x,&f,&n);
      if (a==f) q=n; else w=n;
    scanf("%s %c %d;",z,&g,&m);
      if (a==f) w=m; else q=m;
    while (1)
    {  scanf("%s",e);
     if (strlen(e)==4) break;
      scanf("%c %c",&c,&d);
      gets(z);
      switch(e[0])
      {
       case 'A':if(a==d) q=q+w;
                   else w=q+w;break;
        case 'S':if(a==d) q=q-w;
                   else w=w-q;break;
        case 'M':if(a==d) q=q*w;
                   else w=q*w;break;
        case 'D':if(a==d) q=q/w;
                   else w=w/q;break;
      } }
    printf("%d %d\n",q,w);}
    return 0;
}

G:给出n只袜子,最多k个颜色,一共m天,每天都要穿某两只袜子,不能让某一天穿不同颜色的手套,问至少改变多少只袜子的颜色。思路:把在同一天穿的袜子用并查集放到一起,然后找出最多的那种颜色,size-max即为这堆袜子至少要改的次数。两种解法,并查集,dfs:

并查集解法:

#include <bits/stdc++.h>

using namespace std;

const int maxn = 2e5 + 5;

int pre[maxn], a[maxn], b[maxn];
vector<int> v[maxn];
int Find(int x)
{
    if(pre[x] != x) pre[x] = Find(pre[x]);
    return pre[x];
}
void join(int x, int y)
{
    pre[Find(y)] = Find(x);
}
int main()
{
    int n, m, k, x, y;
    while(~scanf("%d%d%d", &n, &m, &k))
    {
        for(int i = 0;i <= maxn;i++)
            v[i].clear();
        for(int i = 1; i <= n; i++)
            scanf("%d", &a[i]), pre[i] = i;
        for(int i = 1; i <= m; i++)
            scanf("%d%d", &x, &y), join(x, y);
        int cnt = 1;
        for(int i = 1; i <= n; i++)
        {
            if(pre[i] == i)
                b[i] = cnt++;
        }
        for(int i = 1; i <= n; i++)
        {
            v[b[Find(i)]].push_back(a[i]);
        }
        int ans = 0;
        for(int i = 1; i < cnt; i++)
        {
            int maxx = 0;
            map<int, int> mm;
            for(int j = 0; j < v[i].size(); j++)
            {
                mm[v[i][j]]++;
                if(mm[v[i][j]] > maxx)  maxx = mm[v[i][j]];
            }
            ans += v[i].size() - maxx;
        }
        printf("%d\n", ans);
    }
    return 0;
}dfs解法:
#include<bits/stdc++.h>

using namespace std;
typedef long long ll;

int n,m,k;
int x[200005];
vector<vector<int> >v;
int cnt[200005];
int ans,mxc,c;
int vs[200005];

void dfs1(int node)
{
    vs[node]=1;
    for(int i=0; i<v[node].size(); i++)
    {
        if(vs[v[node][i]]==0)
        {
            vs[v[node][i]]=1;
            cnt[x[v[node][i]]]++;
            if(cnt[x[v[node][i]]]>mxc)
            {
                mxc=cnt[x[v[node][i]]];
                c=x[v[node][i]];
            }
            dfs1(v[node][i]);
        }
    }
}

void dfs2(int node)
{
    vs[node]=2;
    for(int i=0; i<v[node].size(); i++)
    {
        if(vs[v[node][i]]==1)
        {
            vs[v[node][i]]=2;
            cnt[x[v[node][i]]]=0;
            if(x[v[node][i]]!=c)
                ans++;
            x[v[node][i]]=c;
            dfs2(v[node][i]);
        }
    }
}

int main()
{
    while(cin>>n>>m>>k)
    {
        ans=0;
        memset(x,0,sizeof(x));
        v.clear();
        for(int i=0; i<n; i++)
            cin>>x[i];
        v.resize(n);
        for(int i=0; i<m; i++)
        {
            int a,b;
            cin>>a>>b;
            a--,b--;
            v[a].push_back(b);
            v[b].push_back(a);
        }
        fill(cnt,cnt+200005,0);
        fill(vs,vs+200005,0);
        for(int i=0; i<n; i++)
        {
            if(vs[i]==0)
            {
                mxc=1;
                c=x[i];
                cnt[x[i]]++;
                dfs1(i);
                cnt[x[i]]--;
                if(x[i]!=c)
                {
                    x[i]=c;
                    ans++;
                }
                dfs2(i);
            }
        }
        cout<<ans<<endl;
    }
    return 0;
}