AtCoder Beginner Contest 200

前言:果然自己连(ABC)都打不好了吗。
没看清题目,卡了巨久,排名一直跌,笔记本键盘坏了,心态崩了。
冷静。
——————————————————————————————————————————————————————
(A)
判断一个年份处于几世纪。

A
// code by fhq_treap
#include<bits/stdc++.h>
#define ll long long
#define N 300005
 
inline ll read(){
    char C=getchar();
    ll A=0 , F=1;
    while(('0' > C || C > '9') && (C != '-')) C=getchar();
    if(C == '-') F=-1 , C=getchar();
    while('0' <= C && C <= '9') A=(A << 1)+(A << 3)+(C - 48) , C=getchar();
    return A*F;
}
 
 
struct P{
	int to,next;
};
 
struct Map{
	P e[N << 1];
	int head[N],cnt;
	Map(){
		std::memset(head,0,sizeof(head));
		cnt = 0;
	}
	inline void add(int x,int y){
		e[++cnt].to = y;
		e[cnt].next = head[x];
		head[x] = cnt;
	}
};
 
ll a;
ll ans = 0;
 
int main(){
	scanf("%lld",&a);
	ans = (a / 100) + (a % 100 != 0);
	std::cout<<ans<<std::endl;
}

(B)
按题意模拟就行。

B
// code by fhq_treap
#include<bits/stdc++.h>
#define ll long long
#define N 300005

inline ll read(){
    char C=getchar();
    ll A=0 , F=1;
    while(('0' > C || C > '9') && (C != '-')) C=getchar();
    if(C == '-') F=-1 , C=getchar();
    while('0' <= C && C <= '9') A=(A << 1)+(A << 3)+(C - 48) , C=getchar();
    return A*F;
}


struct P{
	int to,next;
};

struct Map{
	P e[N << 1];
	int head[N],cnt;
	Map(){
		std::memset(head,0,sizeof(head));
		cnt = 0;
	}
	inline void add(int x,int y){
		e[++cnt].to = y;
		e[cnt].next = head[x];
		head[x] = cnt;
	}
};

ll a,k;

int main(){
	a = read(),k = read();
	for(int i = 1;i <= k;++i){
		if(a % 200 == 0)
		a /= 200;
		else
		a = a * 1000 + 200;
	}
	std::cout<<a<<std::endl;
}

(C)
从左往右扫,按前缀和的膜分类一下就能统计了。

C
// code by fhq_treap
#include<bits/stdc++.h>
#define ll long long
#define N 300005
 
inline ll read(){
    char C=getchar();
    ll A=0 , F=1;
    while(('0' > C || C > '9') && (C != '-')) C=getchar();
    if(C == '-') F=-1 , C=getchar();
    while('0' <= C && C <= '9') A=(A << 1)+(A << 3)+(C - 48) , C=getchar();
    return A*F;
}
 
 
struct P{
	int to,next;
};
 
struct Map{
	P e[N << 1];
	int head[N],cnt;
	Map(){
		std::memset(head,0,sizeof(head));
		cnt = 0;
	}
	inline void add(int x,int y){
		e[++cnt].to = y;
		e[cnt].next = head[x];
		head[x] = cnt;
	}
};
 
ll mod[300];
ll n,a[500005];
ll ans = 0;
 
int main(){
	scanf("%lld",&n);
	for(int i = 1;i <= n;++i){
		a[i] = read();
		ans += mod[a[i] % 200];
		mod[a[i] % 200] ++;
	}
	std::cout<<ans<<std::endl;
}

(D)
五分钟写完三题,感觉良好。
这题一眼看错了题意,以为不能有相同元素,于是乎写了正确算法交了三发(WA)然后就不想打了。
认真看题,不然人没。
一眼看出鸽笼原理,所以只要枚举一群数量大于(200),复杂度在接受范围里的就行。

D
#include<iostream>
#include<cstdio>
#define ll long long
#define N 500

ll n,a[N];

inline ll read(){
	ll ans = 0,f = 1;
	char a = getchar();
	while(a < '0' || a > '9' && a != '-')a = getchar();
	if(a == '-')
	f = -1,a = getchar();
	while(a <= '9' && a >= '0')
	ans = (ans << 3) + (ans << 1) + (a - '0'),a = getchar();
	return ans;
}

ll mod[N];

inline void print(ll a,ll b){
	puts("Yes");
	ll x = 0;
	for(int i = 0;i <= std::min(n - 1,(ll)10);++i)
	if((a >> i) & 1)
	x ++ ;
	std::cout<<x<<" ";
	for(int i = 0;i <= std::min(n - 1,(ll)10);++i)
	if((a >> i) & 1)
	std::cout<<(i + 1)<<" ";
	a = b,x = 0;
	puts("");
	for(int i = 0;i <= std::min(n - 1,(ll)10);++i)
	if((a >> i) & 1)
	x ++ ;
	std::cout<<x<<" ";
	for(int i = 0;i <= std::min(n - 1,(ll)10);++i)
	if((a >> i) & 1)
	std::cout<<(i + 1)<<" ";			
}

int main(){
	n = read();
	for(int i = 1;i <= n;++i)
	a[i] = read() % 200;
	for(int i = 1;i <= (1 << std::min(n - 1,(ll)10));++i){
		ll s = 0;
		for(int j = 0;j <= std::min(n - 1,(ll)10);++j)
		if((i >> j) & 1)
		s = (s + a[j + 1]) % 200;
		if(mod[s]){
			print(mod[s],i);
			return 0;
		}else{
			mod[s] = i;
		}
	}
	puts("No");
}

(E)
这题的关键点在于,如何快速求出三元组和为(s)的数量。
找到答案所在的块内后,完全可以枚举第一,第二个数求解。
考虑找规律,规律见程序。
很抱歉这里说不清。

E
#include <cstdio>
#include <algorithm>
using namespace std;
long long dp[4][3000005];
int ans[4];
int main()
{
    int n,st;
    long long k,sum,now;
    int all;
    scanf("%d%lld",&n,&k);
    dp[0][0]=1;
    for(int i=1;i<=3;i++)
    {
        sum=0;
        for(int j=0;j<=i*n;j++)
        {
            dp[i][j]=sum;
            sum+=dp[i-1][j];
            if(j>=n)
                sum-=dp[i-1][j-n];
        }
    }
    now=0;
    for(int i=0;i<=3*n;i++)
    {
        now+=dp[3][i];
        if(now>=k)
        {
            all=i;
            k-=now-dp[3][i];
            break;
        }
    }
    now=0;
    for(int i=1;i<=n;i++)
    {
        now+=dp[2][all-i];
        if(now>=k)
        {
            ans[1]=i;
            for(int j=1;j<=n;j++)
                if(all-ans[1]-j>=1&&all-ans[1]-j<=n)
                {
                    ans[2]=j;
                    ans[3]=all-ans[1]-ans[2];
                    break;
                }
            for(int j=0;j<k-(now-dp[2][all-i])-1;j++)
            {
                ans[2]++;
                ans[3]--;
            }
            printf("%d %d %d
",ans[1],ans[2],ans[3]);
            break;
        }
    }
    return 0;
}

F找时间补上。

原文地址:https://www.cnblogs.com/dixiao/p/14750490.html