2022牛客暑期多校训练营5 个人题解

57 篇文章 0 订阅
7 篇文章 0 订阅

title :2022牛客暑期多校训练营5 题解
date : 2022-9-21
tags : ACM,练习记录
author : Linno


2022牛客暑期多校训练营5 题解

题目链接 :https://ac.nowcoder.com/acm/contest/33190

补题进度 :9/11

温馨提示:这场因为质量太差unr了。

A-Don’t Starve

因为数据太水,赛时写的记忆化搜索过了,给大家看一眼。(其实是没补题

#pragma GCC optimize("Ofast", "inline", "-ffast-math")
#pragma GCC target("avx,sse2,sse3,sse4,mmx")
#include<bits/stdc++.h>
using namespace std;
const int N=2007;
const int mod=1e9+7;

int read(){	int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-') f=f*-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}return x*f;}
void write(int x){if(x>9) write(x/10);putchar(x%10+'0');}
struct node{
	int x,y;
}s[N];

struct E{
	int v,w;
	bool operator <(E B)const{
		return w<B.w;
	}
};
vector<E>G[N];

int n,vis[N],dp[N][N],ans=0;

inline int dis(node A,node B){
	return (A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y);
}

inline int dfs(int x,int lst){
	if(G[x][0].w>=lst) return 1;  //如果没有边满足条件 
	int L=0,R=n-2,M;
	while(L<R){ 
		M=((L+R+1)>>1);
		if(G[x][M].w<lst) L=M; //二分找到最大的一条满足的边 
		else R=M-1;
	} 
	int idx=L;
	if(idx<=vis[x]) return dp[x][idx]+1; //x已经记录过这条边能走到的点数 
	for(int i=vis[x]+1;i<=idx;++i){ //转移前i条边可以走到的点数 
		int v=G[x][i].v,w=G[x][i].w;
		if(i>0) dp[x][i]=max(dp[x][i-1],dfs(v,w));
		else dp[x][i]=dfs(v,w);
	}
	vis[x]=idx;
	return dp[x][idx]+1;
}

void Solve(){
	scanf("%d",&n);
	for(int i=1;i<=n;++i) scanf("%d%d",&s[i].x,&s[i].y);
	for(int i=1;i<=n;++i){
		for(int j=1;j<=n;++j){
			if(i==j) continue;
			G[i].emplace_back((E){j,dis(s[i],s[j])});
		}
		sort(G[i].begin(),G[i].end()); //按边权从小到大排序 
	}
	memset(vis,-1,sizeof(vis));
	for(int i=1;i<=n;++i){
		ans=max(ans,dfs(i,s[i].x*s[i].x+s[i].y*s[i].y));
	}
	write(ans);putchar('\n');
}

signed main(){
//	srand(time(0));
//	ios::sync_with_stdio(0);
//	cin.tie(0);cout.tie(0);
//  freopen("in.cpp","r",stdin);
//  freopen("out.cpp","w",stdout);
	int T=1;
//	cin>>T;
//	clock_t start,finish;
//	start=clock();
	while(T--){
		Solve();
	}
//	finish=clock();
//	cerr<<((double)finish-start)/CLOCKS_PER_SEC<<endl;
	return 0;
}

B-Watches

二分板。

//#pragma GCC optimize("Ofast", "inline", "-ffast-math")
//#pragma GCC target("avx,sse2,sse3,sse4,mmx")
#include<bits/stdc++.h>
#define inf 0x3f3f3f3f
#define int long long
using namespace std;
const int N=2e5+7;
const int mod=1e9+7;

//int read(){	int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-') f=f*-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}return x*f;}
//void write(int x){if(x>9) write(x/10);putchar(x%10+'0');}
int n,m,a[N],b[N];

bool check(int x){
	int res=0,cnt=0;
	for(int i=1;i<=n;++i){
		b[i]=a[i]+x*i;
	}
	sort(b+1,b+1+n);
	for(int i=1;i<=n;++i){
		if(res+b[i]<=m){
			cnt++;
			res+=b[i];
		}else{
			break;
		}
	}
	if(cnt>=x) return true;
	return false;
} 

void Solve(){
	cin>>n>>m;
	for(int i=1;i<=n;++i) cin>>a[i];
	int L=0,R=n,M;
	while(R-L>1){
		M=(L+R)/2;
		if(check(M)) L=M;
		else R=M;
	}
	if(check(R)) L=R;
	cout<<L<<"\n";
}


signed main(){
	ios::sync_with_stdio(0);
	cin.tie(0);cout.tie(0);
//  freopen("in.cpp","r",stdin);
//  freopen("out.cpp","w",stdout);
	int T=1;
//	cin>>T;
//	clock_t start,finish;
//	start=clock();
	while(T--){
		Solve();
	}
//	finish=clock();
//	cerr<<((double)finish-start)/CLOCKS_PER_SEC<<endl;
	return 0;
}

C-Bit Transmission

这题数据也有大锅,以下是赛时过的代码。

//#pragma GCC optimize("Ofast", "inline", "-ffast-math")
//#pragma GCC target("avx,sse2,sse3,sse4,mmx")
#include<bits/stdc++.h>
//#define inf 0x3f3f3f3f
//#define int long long
using namespace std;
const int N=2e5+7;
const int mod=1e9+7;

//int read(){	int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-') f=f*-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}return x*f;}
//void write(int x){if(x>9) write(x/10);putchar(x%10+'0');}
int n,op,flag,vis[N][3];
char str[10];

void Solve(){
	flag=0;
	memset(vis,0,sizeof(vis));
	for(int i=0;i<3*n;++i){
		scanf("%d%s",&op,str);
		if(str[0]=='Y'){
			vis[op][1]++;
		}else{
			vis[op][0]++;
		}
	}
	for(int i=0;i<n;++i){
		if(vis[i][0]>1&&vis[i][1]>1) flag=1; //存在多次错误回答 
		if(vis[i][0]==vis[i][1]) flag=1;  //都问了一次
		if(vis[i][0]+vis[i][1]<=1) flag=1;
	}
	if(flag) puts("-1");
	else{
		for(int i=0;i<n;++i){
			if(vis[i][0]>vis[i][1]) putchar('0');
			else putchar('1');
		}
		putchar('\n');
	}
}

signed main(){
//	ios::sync_with_stdio(0);
//	cin.tie(0);cout.tie(0);
//  freopen("in.cpp","r",stdin);
//  freopen("out.cpp","w",stdout);
	int T=1;
//	cin>>T;
//	clock_t start,finish;
//	start=clock();
	while(scanf("%d",&n)!=EOF){
		Solve();
	}
//	finish=clock();
//	cerr<<((double)finish-start)/CLOCKS_PER_SEC<<endl;
	return 0;
}

D-Birds in the tree

树形dp。

#include <bits/stdc++.h>
#define int long long
using namespace std;
const int mod=1e9+7;
vector<int> edge[1000005];
int a[1000005],f[1000005],g[1000005],ans;
void dfs(int x)
{
	f[x]=g[x]=1;
	for (int i=0;i<edge[x].size();++i)
	{
		int y=edge[x][i];
		dfs(y);
		f[x]=f[x]*(f[y]+1)%mod;
		g[x]=g[x]*(g[y]+1)%mod;
	}
	if (a[x]==0) { g[x]--; g[x]=(g[x]+mod)%mod;}
	else { f[x]--; f[x]=(f[x]+mod)%mod; }
	ans=ans+f[x]+g[x];
	ans%=mod;
	for (int i=0;i<edge[x].size();++i)
	if (a[x]==0) {
		int y=edge[x][i];
		ans=(ans-g[y]+mod)%mod;
	}
	else
	{
		int y=edge[x][i];
		ans=(ans-f[y]+mod)%mod;
	}
}
signed main()
{
	int n;
	while (scanf("%lld",&n)!=EOF)
	{
		getchar();
		for (int i=1;i<=n;++i)
		 { a[i]=getchar()-'0'; f[i]=g[i]=0; edge[i].clear(); }
		for (int i=1;i<n;++i)
		{
			int x,y;
			scanf("%lld%lld",&x,&y);
			edge[x].push_back(y);
		}
		ans=0;
		dfs(1);
		printf("%lld\n",ans);
	}
	return 0;
}

E-Fraction Game

没补。

F-A Stack of CDs

就是求圆的周长并,随便去套个板子简单粗暴。

#include<bits/stdc++.h>
using namespace std;
const int N = 2005;
const double pi = acos(-1.0);
int read() {
    char ch = getchar(); int x = 0, f = 1;
    while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}
    while(ch >= '0' && ch <= '9') {x = x * 10 + ch - '0'; ch = getchar();}
    return x * f;
}
int cnt, n;
struct dat {double l, r;}opt[N];
bool operator < (dat a, dat b) {return a.l < b.l;}
struct C {
    double x, y, r;
    C(double a = 0, double b = 0, double c = 0) : x(a), y(b), r(c) {}
    C operator - (C a) {return C(x - a.x, y - a.y, 0);}
    double operator ^ (C a) {return x * a.x + y * a.y;}
}p[N];
double sqr(double x) {return x * x;}
double sqr(C a) {return a ^ a;}
double angle(C p) {return atan2(p.y, p.x);}
double angle(double a, double b, double c) {return acos((a * a + b * b - c * c) / (2 * a * b));}
void add(double a, double b) {opt[++cnt].l = a; opt[cnt].r = b;}
void Solve(C u, C v, double dis) {
    double t1 = angle(u - v), t2 = angle(u.r, dis, v.r);
    double l = t1 - t2, r = t1 + t2;
    if(l < 0) l += 2 * pi;
    if(r < 0) r += 2 * pi;
    if(l > r) {add(0, r); add(l, 2 * pi);}
    else add(l, r);
}
double calc() {
    sort(opt + 1, opt + cnt + 1); double l = -10, r = -10, ret = 0;
    for(int i = 1;i <= cnt; ++i) 
    if(opt[i].l > r) {ret += r - l; l = opt[i].l; r = opt[i].r;}
    else r = max(r, opt[i].r);
    ret += r - l; return 2 * pi - ret;
}

signed main() {
    scanf("%d", &n);
    for(int i = n; i; --i) scanf("%lf%lf%lf", &p[i].x, &p[i].y, &p[i].r);
    double ans = 0;
    for(int i = 1, j;i <= n; ++i) {
        cnt = 0;
        for(j = 1;j < i; ++j) {
            double dis = sqrt(sqr(p[j] - p[i]));
            if(p[j].r - p[i].r > dis) break;
            if(p[j].r + p[i].r > dis && fabs(p[j].r - p[i].r) < dis) Solve(p[i], p[j], dis);
        }
        if(j == i) ans += p[i].r * calc();
    }
    printf("%.12lf\n", ans);
    return 0;
}

G-KFC Crazy Thursday

#include <bits/stdc++.h>
using namespace std;
struct dat
{
    unsigned long long f,c,k;
}f[1000005];
unsigned long long g[1000005],hash_head[1000005],hash_tail[1000005],len;
unsigned long long ansc,ansf,ansk;
bool check(int x,int pos)
{
    int l=pos-x;
    int r=pos+x;
    if (l<1||r>len) return false;
    if (hash_head[r]-hash_head[pos-1]*g[x+1]==hash_tail[l]-hash_tail[pos+1]*g[x+1])
        return true;
    else return false;
}
int main()
{
    int n;
    while (scanf("%d",&n)!=EOF)
    {
        char ch;
        char st[1000005];
        getchar();
        len=0;
        for (int i=1;i<=n;++i)
        {
            ch=getchar();
            st[++len]=ch;
            if (i<n) st[++len]='#';
        }
        g[0]=1;
        f[0].c=f[0].f=f[0].k=0;
        for (int i=1;i<=len;++i)
        {
            f[i]=f[i-1];
            if (st[i]=='c') f[i].c++;
            if (st[i]=='f') f[i].f++;
            if (st[i]=='k') f[i].k++;
            g[i]=g[i-1]*131ll;
        }
        hash_head[0]=0;
        hash_tail[len+1]=0;
        for (int i=1;i<=len+1;++i)
        {
            hash_head[i]=hash_head[i-1]*131+st[i];
        }
        for (int i=len;i>=1;i--)
        {
            hash_tail[i]=hash_tail[i+1]*131+st[i];
        }
        ansc=0; ansf=0; ansk=0;
        for (int i=1;i<=len;++i)
        {
            int l,r,mid;
            l=0; r=len-i+1; mid=0;
            while (l+1<r)
            {
                mid=(l+r)>>1;
                if (check(mid,i)) l=mid; else r=mid;
            }
            ansc+=f[i+l].c-f[i-1].c;
            ansf+=f[i+l].f-f[i-1].f;
            ansk+=f[i+l].k-f[i-1].k;
        }
        printf("%lld %lld %lld\n",ansk,ansf,ansc);
        for (int i=0;i<=len+2;++i)
         {
		 	f[i].c=f[i].f=f[i].k=0;
		 	hash_head[i]=hash_tail[i]=0;
		 	g[i]=0;
		 }
    }
    return 0;
}

H-Cutting Papers

用几何画板画出来的东西大概就是圆+矩形的东西。直接求面积。

#include<bits/stdc++.h>
using namespace std;
double PI=3.1415926;
int main()
{
    int n;
    while(scanf("%d",&n)!=EOF)
    {
        double k=n;
        printf("%.10lf\n",
               
    return 0;
}

I-Board Game

一开始多的一定随便摆 把k和多k分开考虑,最后枚举几个k 剩余一定均摊。

#include <bits/stdc++.h>
#define lls __int128
using namespace std;
lls read(){ lls x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-') f=f*-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}return x*f;}
void write(lls x){if(x>9) write(x/10);putchar(x%10+'0');}
typedef  long long ll;
signed main ()
{
    ll nn,mm,kk,xx;
    while(scanf("%lld%lld%lld%lld",&nn,&mm,&kk,&xx))
    {
        lls n=nn;
        lls m=mm;
        lls k=kk;
        lls x=xx;
        if(k==1)
        {
            if(n*(n+1)/2>=x)
            {
                printf("YES ");
                write(n*(n+1)/2);
                printf("\n");
                //printf("%lld\n",n*(n+1)/2);
            }
            else printf("NO\n");
            break;
            continue;
        }
        lls sum1=0;
        lls t=0;
        lls last=n;
        if(n>m*k)
        {
            t=(n-m*k)/k;
            last=n-t*k;
            sum1+=(1ll+t)*t*k/2;
            sum1+=last*t;
        }
        lls ans=0;
        lls kk=0;
        while(last>=0)
        {
            lls d=last/m;
            lls mm=last%m;
            lls tt=(1ll+mm)*mm*(d+1ll)+(m+mm+1)*(m-mm)*d;
            tt/=2ll;
            if(kk*last+tt+(1ll+kk)*kk*k/2>ans)
                ans=kk*last+tt+(1ll+kk)*kk*k/2;
            if(last<k)
                break;
            else {
                last-=k;
                kk++;
            }
        }
        if(ans+sum1>=x)
        {
            printf("YES ");
            write(ans+sum1);
            printf("\n");
        }
        else puts("NO");
        break;
    }
    return 0;
}

J-Check In

没人写的题。

K-Headphones

签到。

//#pragma GCC optimize("Ofast", "inline", "-ffast-math")
//#pragma GCC target("avx,sse2,sse3,sse4,mmx")
#include<bits/stdc++.h>
#define inf 0x3f3f3f3f
#define int long long
using namespace std;
const int N=2e5+7;
const int mod=1e9+7;

//int read(){	int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-') f=f*-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}return x*f;}
//void write(int x){if(x>9) write(x/10);putchar(x%10+'0');}
int n,k;

void Solve(){
	cin>>n>>k;
	int lf=2*n-2*k,ans=lf/2+k+1;
	if(ans+2*k>2*n) cout<<"-1\n";
	else cout<<ans<<"\n";
}

signed main(){
	ios::sync_with_stdio(0);
	cin.tie(0);cout.tie(0);
//  freopen("in.cpp","r",stdin);
//  freopen("out.cpp","w",stdout);
	int T=1;
//	cin>>T;
//	clock_t start,finish;
//	start=clock();
	while(T--){
		Solve();
	}
//	finish=clock();
//	cerr<<((double)finish-start)/CLOCKS_PER_SEC<<endl;
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

RWLinno

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值