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<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
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<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
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<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<ctime>
#include<queue>
#include<map>
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题的面都没见到。。

posted @ 2018-10-20 21:14  dprswdr  阅读(219)  评论(0编辑  收藏  举报