Codeforces Round #513 by Barcelona Bootcamp (rated, Div. 1 + Div. 2)

Codeforces Round #513 by Barcelona Bootcamp (rated, Div. 1 + Div. 2)

  • Solved : 2 out of 8...
  • Rank : 2730 unrated
  • A. Phone Numbers
  • 难度:普及组。
  • 模拟即可。。每个电话号码占用一个'8'和其他10个数码。
  • Summary : 简单题不要浪费过多时间,要提高做题的精度。
  #include
#include
#include
#include
using namespace std;
const int N = 100 + 10;
int cnt =0;
int main(){
    int n; scanf("%d", &n);
    for(int i=1;i<=n;i++) {
        char ch;
        cin>>ch;
        if(ch == '8') cnt++;
    }
    int ans=0;
    while(n){
        if(cnt&&n>=11) cnt--,n-=11,ans++;
        else break;
    }
    printf("%d",ans);
    return 0;
}
  • B. Maximum Sum of Digits
  • 难度: 提高组D1T1?
  • 贪心
    • 对于小于10的数字,a = n, b = 0
    • 对于大于10的数字,我们选择用尽量多的⑨去凑a直到再凑a就会大于n,然后a的最高位就是n的最高位-1,这样就构造出a了。
    • 然后b = n - a。
    • Tips:
      • pow()函数什么的。。。还是自己写个long long的快速幂吧。。。
      • 样例感人。。。还好打了个表找了找规律。。。
    • Summary :
      • 结论题 or 贪心题 一定要打个表写对拍检查一下结论的正确性。
      • 为防止中间量爆long long的情况,在大数据的题目中,能开long long尽量开long long。
      #include
      #include
      #include
      #include
      using namespace std;
      long long cal(long long a){
       long long ans=0;
       while(a){
        long long dig=a%10;
        ans+=dig;
        a/=10;
       }
       return ans;
      }
      long long fpow(long long a,long long b){
       long long ans=1;
       for(;b;b>>=1){
        if(b&1) ans*=a;
        a*=a;
       }
       return ans;
      }
      int main(){
       long long n; scanf("%I64d", &n);
       long long ans;
       long long a ;
       if(n<10) a= n;
       else {
        a = 0;long long cnt=0;
        while(a<=n) a=a*10+9,cnt++;
        if(a>n) a/=10,cnt--;
        long long top;long long x=n;
        while(x){
            if(x/10>0)top=x/10;
            x/=10;
        }
        top--;
        long long pw=fpow(10,cnt);
        a=(long long)top*pw+a;
       }
       long long b ;
       if(n<10) b=0;
       else {
        b = n-a;
       }
       ans = cal(a) + cal(b);
       printf("%I64d",ans);
       return 0;
      }
  • C.Maximum Subrectangle
  • 难度:D1T2
  • 前缀和 + 枚举。。。
    • 我们将\(c_{i,j}=\sum_{i=x_1}^{x_2}\sum_{j=y_1}^{y_2}a_i*b_j\)化成\(c_{i,j}=\sum_{i=x_1}^{x_2}a_i\sum_{j=y_1}^{y_2}b_j=(suma[x_2]-suma[x_1-1])*(sumb[y_2]-sumb[y_1-1])\)。即c可以由a,b的前缀和中各一个区间相乘得到。
    • 由于最终矩形元素和\(\leq x\)即可,所以我们可以预处理出\(suma\)中各长度的和最小的区间and\(sumb\)中各长度的和的最小的区间,然后\(O(n^2)\)枚举a,b各自的长度即可。。。
  • Summary :
    • 要有前缀和优化的意识。。
    • 别把题目想得太难。(当然也别too naive。。
#include
#include
#include
#include
#include
#include
#include
using namespace std;
int read(){
    int x=0,f=1;char ch=' ';
    while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+(ch^'0');ch=getchar();}
    return x*f;
}
const int N = 2000 + 100;
typedef long long ll;
ll a[N], b[N], sa[N], sb[N];
ll ma[N], mb[N];//每种长度的最小区间和 
int main(){
    int n, m; scanf("%d%d", &n, &m);
    sa[0] = sb[0] = 0;
    for(int i = 1; i <= n; i++) scanf("%I64d", &a[i]), sa[i] = sa[i-1] + a[i];
    for(int i = 1; i <= m; i++) scanf("%I64d", &b[i]), sb[i] = sb[i-1] + b[i];
    long long x; scanf("%I64d", &x);
    for(int len = 1; len <= n; len ++){
        ma[len] = (1 << 30); 
        for (int l = 1, r = len; r <= n; l++, r++) ma[len] = min(ma[len], sa[r] - sa[l-1]);
    }
    for(int len = 1; len <= m; len ++){
        mb[len] = (1 << 30); 
        for (int l = 1, r = len; r <= m; l++, r++) mb[len] = min(mb[len], sb[r] - sb[l-1]);
    }
    long long ans = 0;
    for(int i = 1; i <= n; i++){
        for(int j = 1; j <= m; j++){
            if(ma[i] * mb[j] <= x) ans = max(ans, (long long)i*j);
        }
    }
    printf("%I64d", ans);
    return 0;
}

到比赛结束我连E题的面都没见到。。

转载于:https://www.cnblogs.com/Loi-Brilliant/p/9822975.html

你可能感兴趣的:(Codeforces Round #513 by Barcelona Bootcamp (rated, Div. 1 + Div. 2))