3.18周赛补题

A 搜索

思路

  • 找到每个岛 然后判断这个岛有没有沉没
  • 如何判断?
    • N不大,对每个岛进行dfs/bfs,判断岛上每个’#'的情况
    • 能找到不临海的’#',这个岛就不会沉默
    • 不临海就是这个’#‘四周都是’#’
    • 遍历过的要记录,防止重复遍历

代码

#define forr(i,l,r) for(int i=l;i<=r;i++)
const int N=1100;
char a[N][N];
int sum,rm,fg,n;
int dx[4]={0,0,-1,1};
int dy[4]={1,-1,0,0};
void dfs(int x,int y){
    if(fg==0){//还没找到这个岛没被淹没的地方
        int cnt=0;
        forr(i,0,3)cnt+=(a[x+dx[i]][y+dy[i]]=='.');//找周围临海的地方
        if(cnt==0)rm++,fg=1;
    }
    a[x][y]='-';//判断过这个点 记录
    forr(i,0,3){
        int nx=x+dx[i],ny=y+dy[i];
        if(nx>=1&&nx<=n&&ny>=1&&ny<=n&&a[nx][ny]=='#')dfs(nx,ny);
        else continue;
    }
}
void solve(){
    cin>>n;
    forr(i,1,n){
        forr(j,1,n){
            cin>>a[i][j];
        }
    }
    forr(i,1,n){
        forr(j,1,n){
            if(a[i][j]=='#'){
                sum++;//找到一个岛
                fg=0;//判断这个岛有没有没被淹没的
                dfs(i,j);
                //这个岛上面所有的#都变成-了
            }
        }
    }
    // cout<<sum<<' '<<rm<<endl;
    cout<<sum-rm<<endl;
}

B 别想太多 暴力就好

n:1e4 每个数最多四位 枚举每个数再分解数位 暴力能过

inline bool jud(int a){
    while (a)
    {
        int p=a%10;
        if(p==0||p==1||p==2||p==9)return 1;
        a/=10;
    }
    return 0;
}
void solve(){
    int n,sum=0;
    cin>>n;
    forr(i,1,n){
        if(jud(i))sum+=i;
    }
    cout<<sum<<endl;
}

C 同上

void solve(){
    int n;cin>>n;
    int ans=0;
    forr(i,1,n-1){
        int jud=(i*i)%n;
        if(jud*2<n)ans++;
    }cout<<ans;
}

D 数学

思路

  • 最短等差数列 一定是数据最小的是第一项 最大的是最后一项 =>排序
  • 找差:排序后找所有相邻两数之差的共同gcd,那就是所给数据所在等差数列的差

代码

const int N=1e5+10;
int a[N];
void solve(){
    int n;
    cin>>n;
    forr(i,1,n){
        cin>>a[i];
    }
    sort(a+1,a+n+1);
    int q=a[2]-a[1];
    forr(i,3,n){
        q=__gcd(q,a[i]-a[i-1]);
    }
    cout<<(q==0?n:(a[n]-a[1])/q+1)<<endl;//注意差是0的情况
}

E 数学

  • 完全平方数一定是其他完全平方数相乘而来
  • 除去里面的完全平方数 剩下的一定是x
void solve(){
    int n;cin>>n;
    int ans=n,x;
    for(int i=sqrt(n);i>=1;i--){//从大到小找 1e6不会超时
        // cout<<ans<<' '<<i<<endl;
        if(ans%(i*i)==0){
            ans=ans/(i*i);
        }
    }
    
    x=ans;
    cout<<x<<endl;
}

F 搜索

在这里插入图片描述

思路

  • 数据量很小 可以枚举每个属性值
  • 然后判断每次情况的总评分 输出最大的

代码

int f[N];//属性值
struct jud{
    int i,j,op,a,b,d,v;
}p[M];
int n,m,k;
int ans=0;
int vsum(){
    int sum=0;
    forr(x,1,m){
        int cp=f[p[x].i]*p[x].a+f[p[x].j]*p[x].b;//用于比较的数
        switch (p[x].op)
        {
            case 1:
                if(cp>=p[x].d)sum+=p[x].v;
                break;
            case 0:
                if(cp<=p[x].d)sum+=p[x].v;
                break;
        }
    }
    return sum;
}
void dfs(int id){
    if(id>n){
        ans=max(vsum(),ans);
        return;
    }
    forr(x,0,k){
        f[id]=x;
        dfs(id+1);
    }
}
void solve(){
    cin>>n>>m>>k;
    forr(x,1,m){
        cin>>p[x].i>>p[x].j>>p[x].op>>p[x].a>>p[x].b>>p[x].d>>p[x].v;
    }
    dfs(1);
    cout<<ans<<endl;
}

H

const int N=110;
int a[N];
void solve(){
    int x,n;
    cin>>n>>x;
    int sum=0;
    forr(i,1,n){
        cin>>a[i];
        sum+=a[i];
    }
    if(sum%n==0&&sum/n==x)cout<<"Yes"<<endl;
    else cout<<"No"<<endl;
}

I 模拟

题意

  • 三条同时满足
  • 最后一条是或关系

代码

const int N=110;
struct pr{
    int p;
    int c;
    bitset<100>f;//可以用与运算优化
}a[N];
void solve(){
    int n,m;
    cin>>n>>m;
    forr(i,1,n){
        cin>>a[i].p>>a[i].c;
        forr(j,1,a[i].c){
            int ff;
            cin>>ff;
            ff--;//因为bitset从0开始
            a[i].f[ff]=1;
        }
    }
    sort(a+1,a+n+1,[](pr x,pr y){
        return (x.p==y.p?x.c<y.c:x.p>y.p);//排序 价值从大到小 相同价值功能数从小到大,便于判断第二条
    });
    
    forr(i,1,n){
        forr(j,i+1,n){
            if((a[i].f&a[j].f)!=a[i].f)continue;
            if(a[i].p>a[j].p||a[i].f!=a[j].f)return cout<<"Yes"<<endl,void();
        }
    }
    cout<<"No"<<endl;
}

J 字符串

一正一反找就完了

map<string,int>m;
void solve(){
    int n,ans=0;cin>>n;
    forr(i,1,n){
        string s;cin>>s;
        if(m.count(s)==0){
            string re=string(s.rbegin(),s.rend());
            /*逆转 还可以
            reverse(s.begin(),s.end());
            strrev(s);//cstring
            */
            if(m.count(re)==0)m[re]++,ans++;
            else m[re]++;
        }else m[s]++;
    }
    cout<<ans<<endl;
}

K 搜索

const int N=15,M=400;
int a[M],b[M],ans[N],vis[N];
int n,m,t,cnt;
void dfs(int p,int tm){
    if(p==n){
        if(tm)return;//有队空着
        forr(i,1,m){
            if(ans[a[i]]==ans[b[i]])return;
        }
        cnt++;return;
    }
    if(n-p<tm)return;
    forr(i,1,t){
        if(vis[i]){//这个队已经有人了
            ans[p+1]=i;
            dfs(p+1,tm);
        }else {
            ans[p+1]=i;
            vis[i]=1;
            dfs(p+1,tm-1);
            vis[i]=0;
        }
        
    }
}
void solve(){
    cin>>n>>t>>m;
    forr(i,1,m)cin>>a[i]>>b[i];
    dfs(0,t);
    int d=1;
    forr(i,1,t)d*=i;
    cout<<cnt/d<<endl;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值