AtCoder Beginner Contest 319

ABC319 A - Legendary Players

题目传送门


代码(签到题)

#include <cstdio>
#include <cctype>
#include <algorithm>
using namespace std;
int iut(){
	int ans=0; char c=getchar();
	while (!isdigit(c)) c=getchar();
	while (isdigit(c)) ans=ans*10+c-48,c=getchar();
	return ans;
}
int main(){
	char s[21];
	scanf("%s",s+1);
	switch (s[1]){
		case 't':{
			printf("3858");
			break;
		}
		case 'k':{
			printf("3679");
			break;
		}
		case 'B':{
			printf("3658");
			break;
		}
		case 'U':{
			printf("3648");
			break;
		}
		case 'a':{
			printf("3638");
			break;
		}
		case 'S':{
			printf("3630");
			break;
		}
		case 'e':{
			printf("3613");
			break;
		}
		case 'm':{
			printf("3555");
			break;
		}
		case 'n':{
			printf("3516");
			break;
		}
		case 's':{
			printf("3481");
			break;
		}
	}
	return 0;
}

ABC319 B - Measure

题目传送门


代码(签到题)

#include <cstdio>
#include <cctype>
#include <algorithm>
using namespace std;
int iut(){
	int ans=0; char c=getchar();
	while (!isdigit(c)) c=getchar();
	while (isdigit(c)) ans=ans*10+c-48,c=getchar();
	return ans;
}
int main(){
	int n=iut();
	printf("1");
	for (int i=1;i<=n;++i){
		int flag=1;
		for (int j=1;j<=9;++j)
		if (i*j%n==0){
			printf("%d",j);
			flag=0;
			break;
		}
		if (flag) printf("-");
	}
	return 0;
}

ABC319 C - False Hope

题目传送门


分析

比赛时题目没看懂,看懂了就很简单,穷举观察顺序即可


代码

#include <iostream>
#include <iomanip>
#include <algorithm>
using namespace std;
int a[9],rk[9],ans;
bool check(int x,int y,int z){
    if (rk[x]<rk[z]&&rk[y]<rk[z]&&a[x]==a[y]) return 0;
    if (rk[x]<rk[y]&&rk[z]<rk[y]&&a[x]==a[z]) return 0;
    if (rk[y]<rk[x]&&rk[z]<rk[x]&&a[y]==a[z]) return 0;
    return 1;
}
int main(){
    ios::sync_with_stdio(0);
    cin.tie(0),cout.tie(0);
    for (int i=0;i<3;++i)
    for (int j=0;j<3;++j) cin>>a[i*3+j];
    for (int i=0;i<9;++i) rk[i]=i;
    do{
        int flag=check(0,1,2)&check(6,7,8)&check(0,3,6)&check(2,5,8);
        for (int i=0;i<4;++i) flag&=check(4,i,8-i);
        ans+=flag;        
    }while (next_permutation(rk,rk+9));
    cout<<fixed<<setprecision(10)<<ans/362880.0;
    return 0;
}

ABC319 D - Minimum Width

题目传送门


分析

二分答案,判定是否能装入不超过 \(m\)


代码

#include <cstdio>
#include <cctype>
#include <algorithm>
using namespace std;
int n,a[200011],m; long long l,r;
int iut(){
	int ans=0; char c=getchar();
	while (!isdigit(c)) c=getchar();
	while (isdigit(c)) ans=ans*10+c-48,c=getchar();
	return ans;
}
bool check(long long mid){
	int duan=1; long long sum=a[1]+1;
	for (int i=2;i<=n;++i)
	if (sum+a[i]>mid) ++duan,sum=a[i]+1;
	    else sum+=a[i]+1;
	return duan<=m;
}
int main(){
	n=iut(),m=iut();
	for (int i=1;i<=n;++i){
		a[i]=iut(),r+=a[i]+1;
		l=max(l,(long long)a[i]);
	}
	while (l<r){
		long long mid=(l+r)>>1;
		if (check(mid)) r=mid;
		    else l=mid+1;
	}
	printf("%lld",l);
	return 0;
}

ABC319 E - Bus Stops

题目传送门


分析

实际的出发时刻只有 \(lcm(1,\dots,8)=840\) 种情况,直接分类讨论即可


代码

#include <cstdio>
#include <cctype>
#include <algorithm>
using namespace std;
const int N=100011,mod=840;
typedef long long lll;
int n,p[N],t[N],X,Y; long long sum,dp[mod];
int iut(){
	int ans=0; char c=getchar();
	while (!isdigit(c)) c=getchar();
	while (isdigit(c)) ans=ans*10+c-48,c=getchar();
	return ans;
}
void print(lll ans){
	if (ans>9) print(ans/10);
	putchar(ans%10+48);
}
int main(){
	n=iut(),X=iut(),Y=iut(),sum=X+Y;
	for (int i=1;i<n;++i) p[i]=iut(),t[i]=iut(),sum+=t[i];
	for (int j=0;j<mod;++j){
		int x=j;
		for (int i=1;i<n;++i)
		if (x%p[i]==0) x=(x+t[i])%mod;
		    else dp[j]+=p[i]-x%p[i],x=(x+p[i]-x%p[i]+t[i])%mod;
	}
	for (int Q=iut();Q;--Q,putchar(10)){
		int x=iut();
		print(dp[(x+X)%mod]+x+sum);
	}
	return 0;
}

ABC319 F - Fighter Takahashi

题目传送门


分析

七十个点只有一个没过调了一个小时QAQ
由于药的个数很少,设 \(dp[S]\) 表示选取药的状态为 \(S\) 时所能获得的最大力量
那么 \(dp[S|2^j]=\max\{dp[S]\times a_j\}\),显然这是不够的,
每次dp转移好一个状态后,应用贪心不断扩展新的位置,除非该药还未选择或无法到达该位置
显然先加再乘。加的部分可以用布尔数组存下哪些位置未被访问
时间复杂度 \(O(n2^m\log n)\)


代码

#include <cstdio>
#include <cctype>
#include <algorithm>
#include <queue>
#include <bitset>
using namespace std;
const int N=523; long long dp[N<<1];
priority_queue<pair<int,int> >q; bitset<N>v[N<<1];
int n,lim[N],nxt[N],mx,as[N],a[N],m,b[N],rk[N],B[N];
int iut(){
    int ans=0,f=1; char c=getchar();
    while (!isdigit(c)) f=(c=='-')?-f:f,c=getchar();
    while (isdigit(c)) ans=ans*10+c-48,c=getchar();
    return ans*f;
}
int main(){
	n=iut(),lim[1]=mx=1;
	for (int i=2;i<=n;++i){
		int x=iut();
		nxt[i]=as[x],as[x]=i,x=iut();
		lim[i]=iut(),a[i]=iut();
		if (x==2) rk[i]=m,b[m++]=i;
		    else mx=max(mx,lim[i]);
	}
	dp[0]=1;
	for (int S=0;S<(1<<m);++S)
	if (dp[S]){
		q.push(make_pair(-1,1)),B[0]=0;
		while (!q.empty()){
			int x=q.top().second; q.pop();
			if (lim[x]||((S>>rk[x])&1)){
				if (lim[x]>dp[S]){
				    while (!q.empty()) q.pop();
					break;
				}
				if (!v[S][x]&&lim[x]) dp[S]+=a[x],v[S][x]=1;
				for (int y=as[x];y;y=nxt[y])
				    q.push(make_pair(-lim[y],y));
			}else B[++B[0]]=rk[x];
		}
		if (dp[S]>=mx) return !printf("Yes");
		for (int i=1;i<=B[0];++i)
		if (dp[S|(1<<B[i])]<dp[S]*a[b[B[i]]]){
		    dp[S|(1<<B[i])]=dp[S]*a[b[B[i]]],v[S|(1<<B[i])]=v[S];
		    if (dp[S|(1<<B[i])]>=mx) return !printf("Yes");
	    }
	}
	return !printf("No");
}

ABC319 G - Counting Shortest Paths

题目传送门


分析

由于边权均为一,不妨将图分层,可以直接从未访问过的点中选择,复杂度为 \(O(n+m)\)

分层后其实到每个点的最短路只可能从上一层转移而来,容斥一下即可


代码

#include <cstdio>
#include <cctype>
#include <algorithm>
#include <vector>
#include <queue>
#include <map>
using namespace std;
const int N=200011,mod=998244353;
vector<int>G[N]; queue<int>q; map<int,bool>uk[N];
int n,m,dep[N],dp[N],v[N],pre[N],nxt[N],rk[N],L,R,sum;
int iut(){
    int ans=0,f=1; char c=getchar();
    while (!isdigit(c)) f=(c=='-')?-f:f,c=getchar();
    while (isdigit(c)) ans=ans*10+c-48,c=getchar();
    return ans*f;
}
void Mo(int &x,int y){x=x+y>=mod?x+y-mod:x+y;}
bool cmp(int x,int y){return dep[x]<dep[y];}
int main(){
	n=iut(),m=iut();
	for (int i=1;i<=m;++i){
		int x=iut(),y=iut();
		G[x].push_back(y),uk[x][y]=1;
		G[y].push_back(x),uk[y][x]=1;
	}
	for (int i=1;i<=n;++i) nxt[i]=i+1,sort(G[i].begin(),G[i].end());
	for (int i=2;i<=n+1;++i) pre[i]=i-1,dep[i]=n+1;
	q.push(1);
	while (!q.empty()){
		int x=q.front(); q.pop();
		for (int y=nxt[1];y!=n+1;y=nxt[y])
		if (!uk[x][y]){
			dep[y]=dep[x]+1,q.push(y);
			pre[nxt[y]]=pre[y];
			nxt[pre[y]]=nxt[y];
		}
	}
	if (dep[n]==n+1) return !printf("-1");
	for (int i=1;i<=n;++i) rk[i]=i;
	sort(rk+1,rk+1+n,cmp),L=R=1,dp[1]=1;
	for (int l=2,r;l<=n;l=r+1){
		sum=0;
		for (int i=L;i<=R;++i) v[rk[i]]=1,Mo(sum,dp[rk[i]]);
		for (r=l;r<=n&&dep[rk[r]]==dep[rk[l]];++r); --r;
		for (int i=l;i<=r;++i){
			int Sum=sum,siz=G[rk[i]].size();
			for (int j=0;j<siz;++j)
		    if (v[G[rk[i]][j]]) Mo(Sum,mod-dp[G[rk[i]][j]]);
			dp[rk[i]]=Sum;
		    if (rk[i]==n) return !printf("%d",dp[n]);
		}
		for (int i=L;i<=R;++i) v[rk[i]]=0;
		L=l,R=r;
	}
	return 0;
}
posted @ 2024-04-13 02:34  lemondinosaur  阅读(8)  评论(0编辑  收藏  举报