牛客周赛 Round 91【题解完成 】

87 阅读4分钟
题目难度知识点
A while签到
B token签到
C 小苯的逆序对和思维
D 数组4.0★★思维
E 小苯的矩阵反转★ ★暴力枚举
F 小苯的因子查询★★数学

image.png E是会做的,一直死磕F还是不知道咋搞。

while

#include<bits/stdc++.h>
using namespace std;
string a="while";
string s;
int main(void)
{
    cin>>s;
    int ans=0;
    for(int i=0;i<5;i++)
        if(s[i]!=a[i]) ans++;
    cout<<ans;
    return 0;
}

token

#include<bits/stdc++.h>
using namespace std;
const int N=1e5*5+10;
typedef long long int LL;
LL a[N],s[N],n;
int main(void)
{
    cin>>n;
    for(int i=1;i<=n;i++) cin>>a[i],s[i]=s[i-1]+a[i];
    LL ans=0;
    for(int i=1;i<=n;i++)
    {
        ans=max(ans,s[i]-s[max(i-10,0)]);
    }
    cout<<ans;
}

小苯的逆序对和

#include<bits/stdc++.h>
using namespace std;
const int N=1e5*5+10;
int a[N],n,t;
int main(void)
{
    cin>>t;
    while(t--)
    {
        cin>>n;
        for(int i=1;i<=n;i++) cin>>a[i];
        int maxn=a[1],ans=0;
        for(int i=2;i<=n;i++)
        {
            if(a[i]<maxn) ans=max(ans,maxn+a[i]);
            maxn=max(maxn,a[i]);
        }
        cout<<ans<<'\n';
    }
    return 0;
}

数组4.0

#include<bits/stdc++.h>
using namespace std;
const int N=5*1e5+10;
typedef long long int LL;
LL a[N],st[N],t,n;
int main(void)
{
    cin>>t;
    while(t--)
    {
        cin>>n;
        map<LL,int>mp;
        vector<LL>ve;
        for(int i=1;i<=n;i++) 
        {
            cin>>a[i];
            if(mp[a[i]]==0) ve.push_back(a[i]);
            mp[a[i]]++;
        }
        LL ans=n-1;//最多n-1条边就能联通
        sort(ve.begin(),ve.end());
        for(int i=0;i<ve.size();i++)
        {
            if(i+1<ve.size() && ve[i+1]-ve[i]==1)
            {
                int j=i+1;
                while(j<ve.size()&&ve[j]-ve[j-1]==1) j++;//将连续的段合并
                int sum=0;
                j--;
                for(int l=i;l<=j;l++) sum+=mp[ve[l]];//看一共多少个数字
                ans=ans-(sum-1);//将这些已经连的边去掉
                i=j;
            }
        }
        cout<<ans<<'\n';
    }
    return 0;
}

小苯的矩阵反转

自己写的很长的代码

#include<bits/stdc++.h>
using namespace std;
const int N=1010;
int t,n,m,cnt1[N],cnt2[N];
string s[N];
bool check(int x,int y)
{
    int dx[4]={-1,0,0,1};
    int dy[4]={0,-1,1,0};
    int flag=0;
    for(int i=0;i<4;i++)
    {
        int tempx=x+dx[i],tempy=y+dy[i];
        if(tempx>=0&&tempx<n&&tempy>=0&&tempy<m)
            if(s[tempx][tempy]=='1') flag++;
    }
    if(flag)//周围有1
    {
        int cnt=0;
        cnt=cnt1[x]+cnt2[y];
        if( cnt == (n+m-2) )//恰好满足
        {
            for(int i=0;i<m;i++) 
                if(s[x][i]=='1') s[x][i]='0';
                else s[x][i]='1';
            for(int i=0;i<n;i++) 
                if(s[i][y]=='1') s[i][y]='0';
                else s[i][y]='1';    
            return true;
        }
        return false;
    }
    return false;
}
int main(void)
{
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d",&n,&m);
        for(int i=0;i<n;i++)  cin>>s[i];
        for(int i=0;i<n;i++) cnt1[i]=0;
        for(int i=0;i<m;i++) cnt2[i]=0;
        int sum=0;
        for(int i=0;i<n;i++)
            for(int j=0;j<m;j++) 
                if(s[i][j]=='1') cnt1[i]++,sum++;
        for(int i=0;i<m;i++)
            for(int j=0;j<n;j++)
                if(s[j][i]=='1') cnt2[i]++;
        int ans1=0,ans2=0;
        for(int i=0;i<n;i++) if(cnt1[i]==m) ans1++;
        for(int i=0;i<m;i++) if(cnt2[i]==n) ans2++;
        int flag=0;
        if(sum==0)//本来就是全0
        {
            puts("YES");
            continue;
        }
        sum=0;
        if(ans1==2)//2行1
        {   
            for(int i=0;i<n;i++)
                if(cnt1[i]==m)
                    for(int j=0;j<m;j++) s[i][j]='0';
        }
        else if(ans2==2)//2列1
        {
              for(int i=0;i<m;i++)
                if(cnt2[i]==n)
                    for(int j=0;j<n;j++) s[j][i]='0';
        }else{//一行一列
            for(int i=0;i<n;i++)
                for(int j=0;j<m;j++)
                    if(s[i][j]=='0'&&check(i,j))  break;//只执行一次
        }
        for(int i=0;i<n;i++)
            for(int j=0;j<m;j++) 
                if(s[i][j]=='1') sum++;
        if(sum==0) puts("YES");
        else puts("NO");
    }
    return 0;
}

简洁的代码

#include<bits/stdc++.h>
using namespace std;
const int N=1010;
int cnt1[N],cnt2[N],n,m,t;
int dx[4]={-1,0,0,1};
int dy[4]={0,-1,1,0};
string s[N];
bool check(int x,int y)
{
    for(int i=0;i<4;i++)
    {
        int tempx=x+dx[i],tempy=y+dy[i];
        if(tempx<0||tempx>=n||tempy<0||tempy>=m) continue;
        if(s[tempx][tempy]=='0') return false;
    }
    return true;
}
int main(void)
{
    cin>>t;
    while(t--)
    {
        cin>>n>>m;
        for(int i=0;i<n;i++) cin>>s[i];
        for(int i=0;i<n;i++) cnt1[i]=0;
        for(int i=0;i<m;i++) cnt2[i]=0;
        int cnt=0;
        for(int i=0;i<n;i++)
            for(int j=0;j<m;j++)
            {
                if(s[i][j]=='1')
                {
                    cnt1[i]++;
                    cnt2[j]++;
                    cnt++;
                }
            }
        int flag1=0,flag2=0,flag3=0;
        for(int i=0;i<n;i++) 
            if(cnt1[i]==m) flag1++;
        for(int i=0;i<m;i++)
            if(cnt2[i]==n) flag2++;
        for(int i=0;i<n;i++)
            for(int j=0;j<m;j++)
                if( s[i][j]=='0' && check(i,j) ) 
                {
                    if( (cnt1[i]+cnt2[j]) == (n+m-2) ) flag3++;
                }
        if(cnt==0 || (flag1==2 && cnt==m*2 ) || (flag2==2 && cnt==n*2) || (flag3==1 && cnt==(n+m-2)) ) puts("YES");//要么初始就是好的,要么2行,要么2列,要么只有一个满足一行一列的位置,且总1的个数刚好和一次操作翻转的1的数量一样。
        else puts("NO");
    }
    return 0;
}

小苯的因子查询

image.png

image.png

#include<bits/stdc++.h>
using namespace std;
const int N=1e6+10;
const int mod=998244353;
typedef long long int LL;
LL s[N],t,n;
void init(int x)
{
    for(int i=1;i<=x;i++)
    {
        int temp=i;
        while(temp%2==0) s[i]++,temp/=2;
    }
    for(int i=1;i<=x;i++) s[i]+=s[i-1];
}
LL qsm(LL a,LL b,LL p)
{
    LL sum=1;
    while(b)
    {
        if(b&1) sum=sum*a%p;
        a=a*a%p;
        b>>=1;
    }
    return sum%p;
}
int main(void)
{
    init(1e6);
    cin>>t;
    while(t--)
    {
        int n; cin>>n;
        cout<<qsm(s[n]+1,mod-2,mod)<<" ";
    }
    return 0;
}