2019牛客暑期多校训练营(第十场)(B、D、E、F、H、J)

赛中通过

B Coffee Chicken(递归)

n个串的生成方式如下,

第一个串S(1)="COFFEE",第二个串S(2)="CHICKEN",

第n个串S(n) = S(n-2) :: S(n-1),::表示字符串的拼接

给出n(n<=500),k(k<=min(|S(n)|,1e12)),

要求输出第n个串,从第k个字符开始往后10个字符,

如果到串的结尾也不足10个字符,就输出到串的结尾

 

考虑每个字符在哪里显然更便捷一点,不然得分字符串拼接来讨论

赛中讨论了若干,递归搞过去了,赛后补一补别人10minAC的简洁代码

递归:

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
typedef long long ll;
const ll INF=1e13;
int t;
char a[]={"COFFEE"},b[]={"CHICKEN"};
ll fib[505],n,k,v;
void init()
{  
    fib[1]=6;
    fib[2]=7;
    for(int i=3;i<=500;++i)
    fib[i]=min(INF,fib[i-1]+fib[i-2]);
}
void gt(ll n,ll k)
{
    if(n==1){putchar(a[k-1]);return;}
    if(n==2){putchar(b[k-1]);return;}
    if(k<=fib[n-2])gt(n-2,k);
    else gt(n-1,k-fib[n-2]);
}
int main()
{
    init();
    scanf("%d",&t);
    while(t--)
    {
        scanf("%lld%lld",&n,&k);
        for(int i=0;i<=9;++i)
        if(k+i<=fib[n])gt(n,k+i);
        puts("");
    }
    return 0;
}

循环:

#include<iostream>
#include<cstdio> 
#include<cstring>
using namespace std;
typedef long long ll;
const ll INF=1e13;
int t;
char a[]={"COFFEE"},b[]={"CHICKEN"};
ll fib[505],n,k,v;
void init()
{	
	fib[1]=6;
	fib[2]=7;
	for(int i=3;i<=500;++i)
	fib[i]=min(INF,fib[i-1]+fib[i-2]);
}
void gt(ll n,ll k)
{
    while(n>2)
    {
        if(k<=fib[n-2])n-=2;
        else k-=fib[n-2],n--;
    }
    if(n==1)putchar(a[k-1]);
    if(n==2)putchar(b[k-1]);
}
int main()
{
	init();
	scanf("%d",&t);
    while(t--)
    {
        scanf("%lld%lld",&n,&k);
        for(int i=0;i<=9;++i)
        if(k+i<=fib[n])gt(n,k+i);
        puts("");
    }
	return 0;
}

D Han Xin and His Troops(Python+扩展CRT)

一道扩展CRT裸题,姿势不好会爆ll甚至爆__int128

之前的C++大数板子,不带大数%大数和大数/大数,然后就gg了

于是强行把C++的扩展CRT板子改成python的,java的回头再补

def gcd(a, b):
    if b == 0:
        return a
    else:
        return gcd(b, a % b)


def exgcd(a, b):
    if b == 0:
        return 1, 0, a  # x=1 y=0 ans=a
    x, y, r = exgcd(b, a % b)
    tmp = x
    x1 = y
    y1 = tmp - (a // b) * y
    return x1, y1, r


def inv(a, b):
    x, y, r = exgcd(a, b)
    while x < 0:
        x += b
    return x


def excrt(n, m):
    M = []
    C = []
    for i in range(n):
        p, q = map(int, input().split())
        M.append(p)
        C.append(q)
    for i in range(1, n):
        M1 = M[i - 1]
        M2 = M[i]
        C2 = C[i]
        C1 = C[i - 1]
        T = gcd(M1, M2)
        if (C2 - C1) % T != 0:
            print('he was definitely lying')
            return
        M[i] = M1 * M2 // T
        C[i] = (inv(M1 // T, M2 // T) * (C2 - C1) // T) % (M2 // T) * M1 + C1
        C[i] = (C[i] % M[i] + M[i]) % M[i]
    if C[n - 1] > m:
        print('he was probably lying')
        return
    print(C[n - 1])


n, m = map(int, input().split())
excrt(n, m)

E Hilbert Sort(递归分形 排序)

队友抄了个希尔伯特曲线求距离的板子

四叉树和希尔伯特曲线做空间索引_hilbert 四叉树-CSDN博客

先求出每个位置对应的希尔伯特距离,再排序

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int const maxn=1e6+5;
struct node{
    ll x,y,d;
}p[maxn];
bool cmp(node a,node b){
    return a.d<b.d;
}
void rot(ll n, ll *x, ll *y, ll rx, ll ry);
ll xy2d (ll n, ll x, ll y){
    ll rx, ry, s, d=0;
    for (s=n/2; s>0; s/=2)
    {
        rx = (x & s) > 0;
        ry = (y & s) > 0;
        d += s * s * ((3 * rx) ^ ry);
        rot(s, &x, &y, rx, ry);
    }
    return d;
}
void rot(ll n, ll *x, ll *y, ll rx, ll ry){
    if (ry == 0){
        if (rx == 1){
            *x = n-1 - *x;
            *y = n-1 - *y;
        }
        ll t  = *x;
        *x = *y;
        *y = t;
    }
}
int main(){
    ll n,k;
    scanf("%lld%lld",&n,&k);
    ll len=1<<k;
    for(int i=0;i<n;i++){
        scanf("%lld%lld",&p[i].x,&p[i].y);
        p[i].d=xy2d(len,p[i].y-1,p[i].x-1);
    }
    sort(p,p+n,cmp);
    for(int i=0;i<n;i++) printf("%lld %lld\n",p[i].x,p[i].y);
}

F Popping Balloons(线段树)

n(1<=n<=1e5)个气球,第i个气球在(xi,yi)(0<=xi,yi<=1e5)

要求划爆三行三列,使得划爆的气球最大,输出划爆的气球数

要求这三行两两行间距恰为r,三列两两列间距恰为r,r为给定距离(1<=r<=1e5)

 

线段树先按行在对应行i放入(i,i+r,i+2r)行的气球,表示枚举第i行作最左端划破行时的结果

枚举列j作最左端划破列j时,先将j,j+r,j+2r内vector里存的对应行的答案去掉,

避免重复统计,更新答案,再把去掉的答案加回来,

由于i存的是i,i+r,i+2*r,所以vector内行v应消除对应位置v,v-r,v-2*r的影响,此三处存了行v的气球

#include<bits/stdc++.h>
using namespace std;
#define pb push_back
const int N=1e5+10;
const int mx=1e5+1;
int n,r,x,y,dat[4*N],ans;
vector<int>row[N],col[N];
void upd(int p,int l,int r,int x,int v)
{
	if(l==r)
	{
		dat[p]+=v;
		return;
	}
	int mid=(l+r)/2;
	if(x<=mid)upd(p<<1,l,mid,x,v);
	else upd(p<<1|1,mid+1,r,x,v);
	dat[p]=max(dat[p<<1],dat[p<<1|1]);
}
void undo(vector<int> &a,int op)
{
	for(int v:a)
        {
            upd(1,1,mx,v,op);
            if(v-r>=1)upd(1,1,mx,v-r,op);
            if(v-2*r>=1)upd(1,1,mx,v-2*r,op);
	}
}
int main()
{
    scanf("%d%d",&n,&r);
    for(int i=1;i<=n;++i)
    {
        scanf("%d%d",&x,&y);
        x++;y++;
        row[x].pb(y);
        col[y].pb(x);
    }
    for(int i=1;i<=mx;++i)
    {
        int res=row[i].size();
        if(i+r<=mx)res+=row[i+r].size();
        if(i+2*r<=mx)res+=row[i+2*r].size();
        upd(1,1,mx,i,res);
    }
    for(int i=1;i<=mx;++i)
    {
        int tmp=col[i].size();
        if(i+r<=mx)tmp+=col[i+r].size();
        if(i+2*r<=mx)tmp+=col[i+2*r].size();
        undo(col[i],-1);
        if(i+r<=mx)undo(col[i+r],-1);
        if(i+2*r<=mx)undo(col[i+2*r],-1);
        ans=max(ans,dat[1]+tmp);
        undo(col[i],1);
        if(i+r<=mx)undo(col[i+r],1);
        if(i+2*r<=mx)undo(col[i+2*r],1);
    }
    printf("%d\n",ans);
    return 0;
}

H Stammering Chemists(分类讨论)

aHR0cHM6Ly91cGxvYWRmaWxlcy5ub3djb2Rlci5jb20vaW1hZ2VzLzIwMTkwODE0LzMxMzM0N18xNTY1NzE0NTIwMDc0XzUwMjYyRTU3RkUxMTc2NkI0ODhCN0UxOTk1RjZERkJE

T(T<=2e5)组样例,每次给出5条边,判断给定图是以上哪种图

根据度为2、3、4的关系可以确定大部分,

3-methylpentane和2-methylpentane,要对度为3的树根dfs,确定深度

#include<bits/stdc++.h>
using namespace std;
#define pb push_back
typedef long long ll;
int t;
int u,v,deg[7],num[7],mx; 
vector<int>E[7];
void dfs(int u,int fa,int dep)
{
	mx=max(mx,dep);
	for(int v:E[u])
	if(v!=fa)dfs(v,u,dep+1);
}
int main()
{
	scanf("%d",&t);
	while(t--)
	{
		memset(deg,0,sizeof deg);
		memset(num,0,sizeof num);
		mx=0;
		for(int i=1;i<=6;++i)
		E[i].clear();
		for(int i=1;i<6;++i)
		{
			scanf("%d%d",&u,&v);
			E[u].pb(v),E[v].pb(u);
			deg[u]++;
			deg[v]++;
		}
		for(int i=1;i<=6;++i)
		num[deg[i]]++;
		if(num[2]==4)puts("n-hexane");
		else if(num[4]==1)puts("2,2-dimethylbutane");
		else if(num[3]==2)puts("2,3-dimethylbutane");
		else
		{
			int i;
			for(i=1;i<=6;++i)
			if(deg[i]==3)
			{
				dfs(i,-1,0);
				break;
			}
			if(mx==3)puts("2-methylpentane");
			else puts("3-methylpentane");
		}
	}
	return 0;
}

赛后补题

J Wood Processing(斜率dp)

2019牛客暑期多校训练营(第十场) J.Wood Processing(斜率dp)_processing斜率-CSDN博客

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Code92007

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

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

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

打赏作者

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

抵扣说明:

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

余额充值