2019牛客暑期多校训练营(第十场)

B Coffee Chicken

题意:给定S(1)=“COFFEE”,S(2)=“CHICKEN”, S ( n ) = S ( n − 2 ) + S ( n − 1 ) S(n)=S(n-2)+S(n-1) S(n)=S(n2)+S(n1),给定 n 、 k n、k nk,请你输出 S ( n ) S(n) S(n)中第 k k k个字符开始连续的10个字符
思路:递归搜索出k的位置,坑点是k最大是 1 0 12 10^{12} 1012,所以 s ( n ) s(n) s(n)的长度尽管会爆longlong,但其实只需要记录 1 0 12 + 10 10^{12}+10 1012+10即可。递归搜索时如果是到了末尾,不到10个也不用搜

#include <iostream>
#include <string>
#define ll long long
using namespace std;
const ll maxn=1e5+5,INF=1e12+10;

int T,n;
string s1="COFFEE";
string s2="CHICKEN";
ll dp[505],k;

char recursion(int n,ll k)
{
	if(n==1)
		return s1[k-1];
	if(n==2)
		return s2[k-1];
	if(k<=dp[n-2])
		recursion(n-2,k);
	else
		recursion(n-1,k-dp[n-2]);
}

int main()
{
	dp[1]=6,dp[2]=7;
	for(int i=3;i<=500;i++)
	{
		dp[i]=dp[i-2]+dp[i-1];
		dp[i]=min(dp[i],INF);
	}
	cin>>T;
	while(T--)
	{
		cin>>n>>k;
		for(ll i=k;i<k+10&&i<=dp[n];++i)
			cout<<recursion(n,i);
		cout<<"\n"; 
	}
	return 0;
}

D Han Xin and His Troops

题意:求解线性同余方程
思路: x ≡ r 1 ( m o d   a 1 ) x\equiv r_1(mod\ a_1) xr1(mod a1) x ≡ r 2 ( m o d   a 2 ) x\equiv r_2(mod\ a_2) xr2(mod a2),联立得到 a 1 k 1 + r 1 = a 2 k 2 + r 2 a_1k_1+r_1=a_2k_2+r_2 a1k1+r1=a2k2+r2 移项得 a 1 k 1 − a 2 k 2 = r 2 − r 1 a_1k_1-a_2k_2=r_2-r_1 a1k1a2k2=r2r1,得到 k 1 k_1 k1 的一个解 k 1 = k ′ + n × a 2 g c d ( a 1 , a 2 ) k_1=k&#x27;+\frac{n \times a_2}{gcd(a_1,a_2)} k1=k+gcd(a1,a2)n×a2 代回到 x = r 1 + a 1 k 1 x=r_1+a_1k_1 x=r1+a1k1中, x = r 1 + a 1 ( k ′ + n × a 2 g c d ( a 1 , a 2 ) ) x=r_1+a_1(k&#x27;+\frac{n \times a_2}{gcd(a_1,a_2)}) x=r1+a1(k+gcd(a1,a2)n×a2),也就得到了 x = r 1 + a 1 k ′ + a 1 n × a 2 g c d ( a 1 , a 2 ) ) x=r_1+a_1k&#x27;+a_1\frac{n \times a_2}{gcd(a_1,a_2)}) x=r1+a1k+a1gcd(a1,a2)n×a2) x ≡ r 1 + a 1 k ′ ( m o d   a 1 a 2 g c d ( a 1 , a 2 ) ) x\equiv r_1+a_1k&#x27; (mod\ \frac {a_1a_2}{gcd(a_1,a_2)}) xr1+a1k(mod gcd(a1,a2)a1a2)

def exgcd(a,b):
    if b==0:
        return 1,0,a
    y,x,q=exgcd(b,a%b)
    y-=a//b*x
    return x,y,q

def solve(n,a,r):
    a1=a[1]
    r1=r[1]
    for i in range(2,n+1):
        A=a1
        B=a[i]
        M=r[i]-r1;
        X,Y,GCD=exgcd(A,B)
        if M%GCD!=0:
            return -1
        b1=B//GCD
        X=(X*M//GCD%b1+b1)%b1
        r1=r1+a1*X
        a1=a1*a[i]//GCD
    return r1

if __name__ =="__main__":
    n,m=map(int,input().split())
    a=[0]*105
    r=[0]*105
    for i in range(1,n+1):
        a[i],r[i]=map(int,input().split())
    ans=solve(n,a,r)
    if ans==-1:
        print("he was definitely lying")
    elif ans>m:
        print("he was probably lying")
    else:
        print(ans)

E Hilbert Sort

题意:根据递归定义的希尔伯特曲线,给定n个该曲线上的坐标,按顺序输出
思路:对每个点递归计算它的权值。根据当前层的坐标是x,y,讨论出上层的坐标,上层其实就相当于把当前层分为四块的右下角,递归计算即可

#include <iostream>
#include <algorithm>
#define rep(i,a,b) for (int i=a; i<=b; ++i)
#define ll long long
using namespace std;
const int maxn=1e6+5,INF=0x3f3f3f3f;
const int mod=1e9+7;
int n,k;

struct Point
{
	int x,y;
	ll value;
	bool operator<(const Point & b) const
	{
		return value<b.value;
	}
}p[maxn];

ll recursion(int x,int y,int k)
{
	if(k==0)
		return 0;
	ll kk=(1ll<<k);
	ll value=kk*kk;
	if(x<=kk/2&&y<=kk/2)
		return recursion(y,x,k-1);
	else if(x>kk/2&&y<=kk/2)
		return recursion(x-kk/2,y,k-1)+value;
	else if(x>kk/2&&y>kk/2)
		return recursion(x-kk/2,y-kk/2,k-1)+value*2;
	else if(x<=kk/2&&y>kk/2)
		return recursion(kk-y+1,kk/2-x+1,k-1)+value*3;
}

int main()
{
	cin>>n>>k;
	for(int i=1;i<=n;++i)
	{
		cin>>p[i].x>>p[i].y;
		p[i].value=recursion(p[i].x,p[i].y,k);
	}
	sort(p+1,p+1+n);
	rep(i,1,n)
		cout<<p[i].x<<" "<<p[i].y<<"\n"; 
	return 0;
}

F Popping Balloons

题意:给定一个矩阵,矩阵的某些点上有气球,问你怎样选择横三行,竖三行,使得打掉的气球最多。其中三横三竖,相邻两行之间的距离为r

思路:将三行三竖的气球数量,都缩减为一个点,二维数组v[i]表示的是 i i i 这一行,代表的三行中所有气球的列坐标y,把所有竖三行的数量,放进multiset中,每次枚举一个行坐标的时候,就把这个行,代表的三行的所有气球都在列坐标中取消掉。然后取列坐标代表的三列中的最大值。可以使用multiset取,也可以使用线段树取最大值。

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <queue>
#include <vector>
#include <set>
#include <map>
#include <cstring>
#include <string>
#include <cmath>
#define rep(i,a,b) for (int i=a; i<=b; ++i)
#define per(i,b,a) for (int i=b; i>=a; --i)
#define mes(a,b)  memset(a,b,sizeof(a))
#define mp make_pair
#define ll long long
#define pb push_back
#define pii pair<int,int>
#define pll pair<ll,ll>
#define ls (rt<<1)
#define rs ((rt<<1)|1)
#define isZero(d)  (abs(d) < 1e-8)
using namespace std;
const int maxn=1e5+5,INF=0x3f3f3f3f;
const int mod=1e9+7;

int n,r,x,y;
vector<int> v[maxn*3];
vector<int> cnt(maxn*3,0);
multiset<int> s;

void Delete(int k)
{
	auto p=s.find(cnt[k]);
	s.erase(p);
	cnt[k]--;
	s.insert(cnt[k]);
}

void Add(int k)
{
	auto p=s.find(cnt[k]);
	s.erase(p);
	cnt[k]++;
	s.insert(cnt[k]);
}
 
int main()
{
	cin>>n>>r;
	for(int i=1;i<=n;++i)
	{
		cin>>x>>y;
		x+=r;
		y+=r;
		v[x-r].pb(y);
		v[x].pb(y);
		v[x+r].pb(y);
		cnt[y-r]++;
		cnt[y]++;
		cnt[y+r]++;
	}
	for(int i=0;i<maxn+2*r;++i)
		s.insert(cnt[i]);
	int ans=0;
	for(int i=r;i<maxn;++i)
	{
		for(auto it: v[i])
		{
			Delete(it-r);
			Delete(it);
			Delete(it+r);
		}
		auto p=s.rbegin();
		int temp=(int)v[i].size()+(*p);
		ans=max(ans,temp);
		for(auto it: v[i])
		{
			Add(it-r);
			Add(it);
			Add(it+r);
		}						
	}
	cout<<ans<<"\n"; 
	return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值