比赛链接:Dashboard - Educational Codeforces Round 164 (Rated for Div. 2) - Codeforces
A
签到题。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
   | #include<bits/stdc++.h> using namespace std;
  int main() {     int t;     cin>>t;     while(t--)     {         int n,m,k;         cin>>n>>m>>k;         if(n/m*(m-1)+max(n%m-1,0)>k)cout<<"YES\n";         else cout<<"NO\n";
      }     return 0; }
   | 
 
B
题意:给出一个长为 $n$ 的数组 $a$ ,现在需要删除几个元素,使得最后的数组不满足以下条件:通过数次操作选择相等的 $a_{i-1}$ 与 $a_{i+1}$ ,将 $a_i$ 替换为这个数后,整个数组变得相等。
最后得到的数一定是 $a[1]$ 或者 $a[n]$ ,模拟发现要删除的元素个数就是连续的最小长度的 $a[1]$ 。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
   | #include<bits/stdc++.h> using namespace std;
  void solve() {     int n;     cin>>n;     int a[n+5];     for(int i=1;i<=n;i++)cin>>a[i];     if(a[1]!=a[n])     {         cout<<"0\n";         return;     }
      int st=a[1];     int ans=3e5+5;     int cnt=0;     for(int i=1;i<=n;i++)     {            if(a[i]==st)cnt++;         else         {             if(cnt==0)             {                 cout<<"0\n";                 return;             }             ans=min(ans,cnt);             cnt=0;         }     }     ans=min(ans,cnt);     if(ans>=n)cout<<"-1\n";     else cout<<ans<<endl; }
  int main() {     int t;     cin>>t;     while(t--)solve();     return 0; }
   | 
 
C
题意:给出两个长度相等的数 $x,y$ ,可以交换相同数位上的数,最后要使得 $x\times y$ 最大。
注意到 $x+y$ 是一个定值,要使 $x\times y$ 最大,那么就要使 $x,y$ 尽可能接近。假设 $x>y$ ,那么从高位枚举,使 $x$ 某一位上的数比 $y$ 相同位小即可。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
   | #include<bits/stdc++.h> using namespace std;
  void solve() {     string x,y;     cin>>x>>y;
      int s;     int len=x.length();     int pos=-1;     for(int i=0;i<len;i++)     {         if(x[i]==y[i])continue;         s=x[i]>y[i];         pos=i;         break;     }
      if(pos==-1)     {         cout<<x<<endl<<y<<endl;         return ;     }
      for(int i=pos+1;i<len;i++)     {         if(s==1)         {             if(x[i]>y[i])swap(x[i],y[i]);         }         else         {             if(x[i]<y[i])swap(x[i],y[i]);         }     }
      cout<<x<<endl<<y<<endl;
  }
  int main() {     int t;     cin>>t;     while(t--)solve();     return 0; }
   | 
 
D
题意:有 $n$ 种不同的颜色,每种颜色的球有 $a_i$ 个。现在选某几种颜色的所有球视为一类,那么共有 $2^n$ 类,并将其分组,分组规则如下:每一组不超过两个球,且不能有相同颜色的球,且要使分的组数尽可能少。求所有类的分组的个数的总和。$a_1+…+a_n\leq 5000$
考虑对于某一类,如何分组最优。假设数量最多的球的个数是 $a_n$ ,总和是 $sum$ 。
- 若 $a_n\geq sum-a_n$,那么组数就是就是 $a_n$ 。具体方法为每一个 $a_n$ 配一个其他颜色的球。
 
- 若 $a_n\leq sum-a_n$ ,那么组数就是 $\lceil sum/2\rceil$ 。
 
因此可以采用如下方法进行统计:利用背包现将所有组合按照 $\lceil sum/2\rceil$ 进行统计,然后再补偿 $a_n\geq sum-a_n$ 的情况。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
   | #include<bits/stdc++.h> using namespace std; #define int long long const int mod=998244353; int a[5005]; int dp[5005];
  signed main() {     int n;     cin>>n;     int sum=0;     int ans=0;     for(int i=1;i<=n;i++)cin>>a[i],sum+=a[i];
      memset(dp,0,sizeof(dp));     dp[0]=1;          for(int i=1;i<=n;i++)     {         for(int j=sum;j>=a[i];j--)         {             dp[j]=(dp[j]+dp[j-a[i]])%mod;         }     }
      for(int i=1;i<=sum;i++)     {         ans=(ans+(i+1)/2*dp[i]%mod)%mod;     }          for(int i=1;i<=n;i++)     {         for(int j=0;j<a[i];j++)         {             ans=(ans+(a[i]-(j+a[i]+1)/2)*dp[j]%mod)%mod;         }     }     cout<<ans;     return 0; }
   | 
 
E
题意:有 $n$ 个怪兽,每个怪兽的生命值是 $a_i$ 。通过连锁反应进行攻击:每次选择一个没死的怪兽作为攻击起点,对其进行 $k$ 点攻击,然后攻击朝左边和右边扩散,都造成 $k$ 点攻击,直到遇到一个已经死亡的怪兽才停下来。对于 $k=1,2,…,max\ a_i$ ,分别求出最少杀死所有怪物的施法次数。
考虑 $k=1$ 的情况,可以发现攻击的次数即为 $\sum max(0,a_i-a_{i-1})$ 。可以考虑将其转换成一个至于本身有关的多项式,即转化为 $\sum c_ia_i$ 。关于系数 $c_i$ ,可以有如下方式确定:初始 $c_i=0$ ,若 $a_i>a_{i-1}$ ,$c_i++$ ,若 $a_i<a_{i+1}$ ,$c_i–$ 。
对于 $k>1$ 的情况,只需将 $a_i$ 变成 $\lceil a_i/k\rceil$ 即可。
关于统计答案对于某一个 $k$ ,可以观察到 $\lceil a_i/k\rceil$ 是根据 $k$ 分段的,即按照以下方式统计:
$$
1\times \sum_{i=1,…,k} c_i+2\times\sum_{i=k+1,…,2k}c_i+…
$$
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
   | #include<bits/stdc++.h> using namespace std; #define LL long long
  int main() {     int n;     cin>>n;     int a[n+2];     int mx=0;     for(int i=1;i<=n;i++)     {         cin>>a[i];         mx=max(mx,a[i]);     }
      int ad[mx+1]={0};     for(int i=1;i<=n;i++)     {         int c=0;         if(i==1 || a[i]>a[i-1])c++;         if(i<n && a[i]<a[i+1])c--;         ad[a[i]]+=c;     }
      for(int i=1;i<mx;i++)ad[i+1]+=ad[i];
      for(int k=1;k<=mx;k++)     {         LL ans=0;         for(int val=1,l=1;l<=mx;l+=k,val++)         {             ans+=1LL*val*(ad[min(l+k-1,mx)]-ad[l-1]);         }         cout<<ans<<" ";     }     return 0; }
   |