半个和尚 發表於 2025-4-29 10:59:00

牛客周赛91题解

<h1 id="牛客周赛91">牛客周赛91</h1>
<p>https://ac.nowcoder.com/acm/contest/108038#question</p>
<h3 id="awhile">A.while</h3>
<p>https://ac.nowcoder.com/acm/contest/108038/A</p>
<p>签到题:只需要判断当前字符串与<code>while</code>有多少个位置上的字符不相同即可。</p>
<pre><code class="language-cpp">#include&lt;bits/stdc++.h&gt;
using namespace std;
int main()
{
    string s;cin&gt;&gt;s;
    int ans=0;
    if(s!='w') ans++;
    if(s!='h') ans++;
    if(s!='i') ans++;
    if(s!='l') ans++;
    if(s!='e') ans++;
    cout&lt;&lt;ans;
    return 0;
}
</code></pre>
<h3 id="btoken">B.token</h3>
<p>https://ac.nowcoder.com/acm/contest/108038/B</p>
<p>签到题,用前缀和解决即可。</p>
<pre><code class="language-cpp">#include&lt;bits/stdc++.h&gt;
using namespace std;
#define LL long long
int main()
{
    int n;cin&gt;&gt;n;
    vector&lt;LL&gt; a(n+1,0),s(n+1,0);
    for(int i=1;i&lt;=n;i++) cin&gt;&gt;a,s=s+a;
    LL ans=0;
    for(int i=1;i&lt;=n;i++){
      if(i&lt;=9) ans=max(ans,s);
      else ans=max(ans,s-s);      
    }
    cout&lt;&lt;ans;
    return 0;
}
</code></pre>
<h3 id="c小苯的逆序对和">C.小苯的逆序对和</h3>
<p>https://ac.nowcoder.com/acm/contest/108038/C</p>
<p>思路:预处理出前i个数中最大的数的值<code>p</code>,然后枚举下标<span class="math inline">\(i\)</span>,若<code>p&gt;a</code>,也就是说,下标i前面的值有&gt;a的部分,那么可以构成逆序对,因为要求最大的<code>a+a</code>,故而我们处理出前i个数中最大的值即可。</p>
<pre><code class="language-cpp">#include&lt;bits/stdc++.h&gt;
using namespace std;
void solve(){
    int n;cin&gt;&gt;n;
    //预处理前i个数中的最大值
    vector&lt;int&gt; a(n+1,0),p(n+1,0);
    for(int i=1;i&lt;=n;i++){
      cin&gt;&gt;a;
      p=max(p,a);
    }
    int ans=0;
    for(int i=1;i&lt;=n;i++){
      if(p&gt;a) ans=max(p+a,ans);
    }
    cout&lt;&lt;ans&lt;&lt;"\n";
}

int main()
{
    int t=1;cin&gt;&gt;t;
    while(t--) solve();
    return 0;
}
</code></pre>
<h3 id="d数组40">D.数组4.0</h3>
<p>https://ac.nowcoder.com/acm/contest/108038/D</p>
<p>思路:将数组中的元素进行排序以后,计算“段数”,那么答案就是“段数”-1,怎么计算段数呢?当我们以一个数<code>x</code>新开一段时,意味着<code>x-1</code>在数组中必然不存在,那么我们只需要用<code>map</code>来存储每个数出现的频率,(至于为什么用map,不用set,后面有解释。)如果<code>x-1</code>出现的频率为0,那么就新开一段。</p>
<p>那么为什么我们使用<code>map</code>而不使用<code>set</code>呢?我们有一种特殊情况,类似下列样例:</p>
<p><code></code>这个样例,我们需要在<code>2,4</code>之间连接一条边,也需要在<code>4,4</code>和<code>4-6</code>之间连一条边,也就是说:当<code>x+1</code>在数组中不存在时,我们需要将所有的x之间连接起来,将所有x连接起来的代价是:<code>x出现的频率-1</code>;</p>
<pre><code class="language-cpp">#include&lt;bits/stdc++.h&gt;
using namespace std;
void solve(){
    int n;cin&gt;&gt;n;
    map&lt;int,int&gt; mp;
    for(int i=1;i&lt;=n;i++){
      int x;cin&gt;&gt;x;
      mp++;
    }
    int ans=0;
    for(auto &amp; : mp){
      //x-1不存在,就新开一段
      if(!mp.count(x-1)){
            ans++;
            //若x+1不存在,那么需要将所有的x自行连接起来...
            if(!mp.count(x+1)) ans+=y-1;
      }
    }
    //答案为“段数”-1;
    cout&lt;&lt;ans-1&lt;&lt;"\n";
}
int main()
{
    int t=1;cin&gt;&gt;t;
    while(t--) solve();
    return 0;
}
</code></pre>
<h3 id="e小苯的矩阵反转">E.小苯的矩阵反转</h3>
<p>https://ac.nowcoder.com/acm/contest/108038/E</p>
<p>思路:如果给我们一个01矩阵,让我们判断是否能变成全0矩阵,这样或许有点麻烦,有很多种情况需要讨论,那么我们不妨反过来思考,给我们一个全0矩阵,经过这几种操作之后,能够变成什么样的矩阵,然后将这个矩阵和我们原本的01矩阵进行匹配,如果匹配成功,那么就输出<code>YES</code>,否则输出<code>NO</code>;<br>
那么给我们一个01矩阵,进行这几种操作以后,可以有四种情况:</p>
<ol>
<li>选择全0的一行(列)进行翻转两次,得到的矩阵还是全0矩阵</li>
<li>选择全0的两行(这两行不同)分别翻转一次,得到的矩阵是:只有两行全是1,其余行都是0;</li>
<li>选择全0的两列(这两列不同)分别翻转一次,得到的矩阵是:只有两列全是1,其余列都是0;</li>
<li>选择一行和一列进行操作,翻转一次。那么得到的会是一个十字架类型的图形,除了交叉点,其余点都是1;</li>
</ol>
<p>那么如何写代码进行判断呢?</p>
<ol>
<li>
<p>全0的情况很容易判断,只需要数字符1的个数<code>c1</code>,若<code>c1==0</code>,那么这个01矩阵原本就是全0矩阵</p>
</li>
<li>
<p>选择两行进行翻转,那么翻转以后,得到的矩阵中的1的个数必然为<code>m*2</code>,并且其他行都是0,我们只需要用一个变量<code>Cr</code>来记录全是0是行的个数,若<code>Cr==2 &amp;&amp; c1==m*2</code>,那么就符合我们这种情况。</p>
</li>
<li>
<p>选择两列翻转,与第二条同理。我们用<code>Cc</code>来记录 全0的列数的个数,若<code>Cc==2 &amp;&amp; c1==n*2</code>,那么就符合情况</p>
</li>
<li>
<p>十字架类型的图形,这种情况,因为交点是0,那么我们只需要枚举0的位置,假设当前行列的位置分别为<code>i,j</code>。那么我们只需要判断<code>第i行中1的个数是否为m-1</code>以及<code>第j列中1的个数是否为n-1</code>,以及<code>字符1的个数为n+m-2</code>;如果三条都满足,那么就符合这种情况。在这里我们需要用<code>r</code>来记录第i行中1的个数,还需要用<code>c</code>来记录第j列中1的个数</p>
</li>
</ol>
<pre><code class="language-cpp">//正难则反
//考虑四种情况
//1.原本就是全0
//2.有两列/行为1
//3.有一个十字架型的形状(除了交点以外都是1);

#include&lt;bits/stdc++.h&gt;
using namespace std;
void solve(){
    int n,m;cin&gt;&gt;n&gt;&gt;m;
    vector&lt;string&gt; a(n);
    //r表示第i行中1的个数,..c表示第i列中1的个数
    vector&lt;int&gt; r(n),c(m);
    for(int i=0;i&lt;n;i++) cin&gt;&gt;a;
    //算1的个数
    int c1=0;
    for(int i=0;i&lt;n;i++){
      for(int j=0;j&lt;m;j++){
            if(a=='1'){
                c1++;
                //第i行,第j列
                r++;
                c++;
            }
      }
    }
    //计算全是1的行数的个数
    int Cr = 0;
    for(int i = 0; i &lt; n; i++) {
      Cr += (r == m);
    }
    //计算全为0的列数的个数
    int Cc = 0;
    for(int i = 0; i &lt; m; i++) {
      Cc += (c == n);
    }
    //还有类似十字架的图形,枚举0的位置..那么那行的1的个数为m-1,那一列的1的个数为n-1..且总的1的个数为n+m-2;
    bool flag=0;
    for(int i=0;i&lt;n;i++){
      for(int j=0;j&lt;m;j++){
            if(a=='1') continue;
            if(r==m-1&amp;&amp;c==n-1&amp;&amp;c1==n+m-2) flag=true;
      }
    }
    //满足一种情况,那么就输出YES,否则为NO;
    if(c1==0||(c1==2*m &amp;&amp; Cr==2)||(c1==2*n &amp;&amp; Cc==2)||flag) cout&lt;&lt;"YES\n";
    else cout&lt;&lt;"NO\n";
}
int main()
{
    int t=1;cin&gt;&gt;t;
    while(t--) solve();
    return 0;
}
</code></pre>
<h3 id="f小苯的因子查询">F.小苯的因子查询</h3>
<p>https://ac.nowcoder.com/acm/contest/108038/F</p>
<p>有待更新....</p><br><br>
来源:https://www.cnblogs.com/Tomorrowland/p/18853293
頁: [1]
查看完整版本: 牛客周赛91题解