首页 > 其他分享 >牛客第一场补题

牛客第一场补题

时间:2023-07-23 13:11:45浏览次数:36  
标签:return ai ll 牛客 int maxn 补题 ans 第一场

牛客多校1

D. Chocolate

题意:

A、B轮流吃巧克力,当一个人选择一个点吃的时候,会把这个点及其左下的所有全部吃完,谁先吃完谁就输了,给出巧克力的大小,问谁会赢。

思路:

考虑当一个人吃完只剩一行或一列时,那么下一个吃的人就可以控制把最后一块留给这个人,因此当一个人吃完剩一行和一列的时候,就可以控制剩下一行或者剩下一列给谁,因此除非初始巧克力大小只有1*1,否则先手必胜

#include<bits/stdc++.h>
using namespace std;

int main(){
    int x, y;
    cin>>x>>y;
    if(x == 1 && y == 1){
        cout<<"Walk Alone\n";
    }
    else{
        cout<<"Kelin\n";
    }
    return 0;
}

L.Three Permutations

题意:

初始点(1, ,1 , 1),给出三个排列a, b, c,每次x->a[y], y->b[z], z->c[x],给出q组询问,每次询问给出x'、y'、z',问最少经过多少秒到达(x',y',z'),若无法到达,输出-1

思路:

显然每三秒x->abc[x], y->bca[y], z->cab[z],此时这个置换只和我当前对应的x,y,z有关,因此可以通过这个置换得到循环节大小、在一个循环里到达某一个位置的时间。然后对于每一个询问,枚举从第0秒、第1秒、第2秒开始所能到达的时间,用扩展中国剩余定理即可求得答案。

#include<bits/stdc++.h>
using namespace std;
using ll = long long;

const int maxn = 1e5 + 10;
int n, q;
ll a[maxn], b[maxn], c[maxn];
ll ia[maxn], ib[maxn], ic[maxn];
ll abc[maxn], bca[maxn], cab[maxn];
ll dista[maxn], distb[maxn], distc[maxn];
ll mi[5], ai[5];

ll exgcd(ll a, ll b, ll &x, ll &y){
	if(b == 0){
		x = 1, y = 0;
		return a;
	}

	ll d = exgcd(b, a % b, y, x);
	y -= a/b * x;
	return d;
}

ll excrt(){
    ll x, y;
    ll a1 = ai[1], m1 = mi[1];
    ll ans = 0;
    for(int i = 2; i <= 3; i++){
        ll a2 = ai[i], m2 = mi[i];
        ll a = m1, b = m2, c = (a2 - a1 % m2 + m2) % m2;
        ll d = exgcd(a, b, x, y);
        if( c % d != 0) return -1;
        x = x * (c / d)  % (b / d);
        ans = a1 + x * m1;
        m1 = m2 / d * m1;
        ans = (ans % m1 + m1) % m1;
        a1 = ans;
    }
    return ans;
}


void query(){
	cin>>q;
	while(q--){
		int x, y, z;
		cin>>x>>y>>z;
		ll t1, t2, t3;
		ai[1] = dista[x];
		ai[2] = distb[y];
		ai[3] = distc[z];
		if(ai[1] == -1 || ai[2] == -1 || ai[3] == -1) t1 = -1;
	    else t1 = excrt();

	    ai[1] = dista[ic[z]];
	    ai[2] = distb[ia[x]];
	    ai[3] = distc[ib[y]];
	    if(ai[1] == -1 || ai[2] == -1 || ai[3] == -1) t2 = -1;
	    else t2 = excrt();;

	    ai[1] = dista[ic[ib[y]]];
	    ai[2] = distb[ia[ic[z]]];
	    ai[3] = distc[ib[ia[x]]];
	   	if(ai[1] == -1 || ai[2] == -1 || ai[3] == -1) t3 = -1;
	    else t3 = excrt();

	    ll ans = 1e18;
	    if(t1 != -1) ans = min(ans, 3 * t1);
	    if(t2 != -1) ans = min(ans, 3 * t2 + 1);
	    if(t3 != -1) ans = min(ans, 3 * t3 + 2);
	    if(ans == 1e18) cout<<"-1\n";
	    else cout<<ans<<"\n";
	}
}


void solve(){
	memset(dista, -1, sizeof(dista));
	memset(distb, -1, sizeof(distb));
	memset(distc, -1, sizeof(distc));
	cin>>n;
	for(int i = 1; i <= n; i++) cin>>a[i], ia[a[i]] = i;
	for(int i = 1; i <= n; i++) cin>>b[i], ib[b[i]] = i;
	for(int i = 1; i <= n; i++) cin>>c[i], ic[c[i]] = i;



	for(int i = 1; i <= n; i++) abc[i] = a[b[c[i]]];
	for(int i = 1; i <= n; i++) bca[i] = b[c[a[i]]];
	for(int i = 1; i <= n; i++) cab[i] = c[a[b[i]]];

	ll ta = 0, tb = 0, tc = 0;
	for(ll i = 1; dista[i] == -1; i = abc[i], ++ta) dista[i] = ta;
	for(ll i = 1; distb[i] == -1; i = bca[i], ++tb) distb[i] = tb;
	for(ll i = 1; distc[i] == -1; i = cab[i], ++tc) distc[i] = tc;
	mi[1] = ta, mi[2] = tb, mi[3] = tc;
	query();
}

int main(){
	cin.tie(0);
	ios::sync_with_stdio(false);
	int T = 1;
	//cin>>T;
	while(T--){
		solve();
	}
	return 0;
}

M.Water

题意:

初始有两个空水杯,容量为a, b,然后要通过倒水、转移的操作喝到d容量的水,并且喝也算一次操作,问最少操作几次能喝到d的水。

思路:

显然若ax+by=d无解时输出-1。那么当有解时怎样得到操作最少呢。

当x>=0, y>=0时,ans = 2 * (x + y);

否则,ans = 2 *abs(x - y) - 1

通过观察一次函数可以发现再原点附近的(x + y)最小。

因此,通过扩展欧几里得求得x, y后先得到原点附近的x, y,再枚举其左右两个点对答案取小。

#include<bits/stdc++.h>
using namespace std;
using ll = long long;

const int maxn = 1e6 + 10;
ll n, m, k;
ll a ,b , c;
ll ans = 1e18;

ll exgcd(ll a, ll b, ll &x, ll &y){
	if(b == 0){
		x = 1;
		y = 0;
		return a;
	}

	ll d = exgcd(b, a % b, y, x);
	y -= a / b * x;
	return d;
}


void calc(ll t, ll x, ll y){
	ll s = x + t * b, r = y - t * a;
	if(s >= 0 && r >= 0){
		ans = min(ans, 2*(s + r));
	}
	else{
		ans = min(ans, 2*(abs(s) + abs(r)) - 1);
	}
}

void solve(){
	cin>>n;
	for(int i = 1; i <= n; i++){
		ans = 1e18;
		cin>>a>>b>>c;
		if(a > b) swap(a, b);
		ll x ,y;
		ll d = exgcd(a, b ,x , y);
		if(c % d != 0){
			cout<<"-1\n";
			continue;
		}
		a /= d, b /= d, c /= d, x *= c, y *= c;
		ll t0 = -x / b;
		for(int t = t0 - 1; t <= t0 + 1; t++){
			calc(t, x, y);
		}

		t0 = y / a;
		for(int t = t0 - 1; t <= t0 + 1; t++){
			calc(t, x, y);
		}

		cout<<ans<<"\n";
	}
	
}

int main(){
	cin.tie(0);
	ios::sync_with_stdio(false);
	int T = 1;
	//cin>>T;
	while(T--){
		solve();
	}
	return 0;
}

标签:return,ai,ll,牛客,int,maxn,补题,ans,第一场
From: https://www.cnblogs.com/pang-bai/p/17574901.html

相关文章

  • 杭电多校第一场补题
    杭电多校第一场1001Hide-And-SeekGame题意:给出一棵树,每次询问第一个人从Sa-Sb之间来回走,第二个人在Ta-Tb之间来回走,最早相遇的节点,如果无法相遇就输出-1做法:由于数据量是1e3级别,因此对于每一条路径都可以使用暴力找祖先的方法求出路径,然后对于路径上的每一个节点,其出现的时间......
  • 2023牛客暑期多校训练营2 补题
    D.TheGameofEating题意:有n个人和m道菜,每个人对每个菜的都有一个喜好度a[i][j],所有人都知道其他人的喜好度,现在需要上k道菜,从1,2...,n,1,2.....的顺序来选,如果每个人都只考虑自己的喜好,问最后哪些菜会被端上来Solution我们考虑到所有人都知道其他人的喜好度,也就是说,假设当前要选......
  • 牛客多校2
    D.TheGameofEating题意:有\(n\)个人,\(m\)种菜,从\(1\)开始轮流点菜,一共点\(k\)道,\(n\)点完轮到\(1\),直到点完,点过的菜其他人不能再点。第\(i\)个人对第\(j\)道菜有\(A_{i,j}\)的喜好度,每个人都想让自己对所有已选的菜的喜好度总和最大,他们能彼此看到对菜的喜好度,问最后点了的......
  • 暑假牛客多校第二场 2023-7-21
    未补完E.Square算法:二分做法:我们依据x来枚举k,得到\(x*10^k\),用二分在[0,1e9]查找mid的平方值,且这个值是第一个大于等于\(x*10^k\)的值。得到这个值后我们再判断这个值在除\(10^k\)后是否与\(x\)相等即可。code#include<iostream>#include<cstring>#incl......
  • 2023牛客多校7.21补题
    D-TheGameofEating题意:一共有m道菜,n个人轮流点一道菜,一共点k道。第i个人对第j道菜的喜爱程度\(A_{i,j}\)对所有人公开,一个人点了菜所有人都可以吃到。每个人都希望最大化自己的喜爱程度之和,求最终的点菜集合。分析:很容易想到每个人点菜时都点当前剩下的菜中自己最喜爱的,但是......
  • Codeforces Round 886 (Div. 4)补题
    CodeforcesRound886(Div.4)A~D://A:boolsolve(){ cin>>a[1]>>a[2]>>a[3]; sort(a+1,a+4); returna[2]+a[3]>=10?1:0;}//B:voidsolve(){ intn; cin>>n; intmaxa=0; intnum=0; intx,y; for(inti=1;i<=n;i++){cin>......
  • 牛客暑假多校 2023 第二场
    写在前面比赛地址:https://ac.nowcoder.com/acm/contest/57356。我是MINUS-FIFTEEN级超级战犯。澄清一下,我不是声优厨,我不是声优厨,我不是声优厨。同样是题目选补,我是飞舞。以下个人向难度排序。I签到。随便手玩一下就行。D虽然每个人都倾向于吃到自己最喜欢的菜,但给在......
  • 2023 牛客暑期多校
    7.17我正开,Dgjk倒开,AHJKLMA-AlmostCorrect设\(s\)中\(0\)的下标集合为\(S_{0}\),\(1\)的为\(S_{1}\),最右边的\(0\)的下标\(r\),最左边\(1\)的下标\(l\)。\(s\)没有排好序所以\(l\le|S_{1}|<r\)\(\foralli\inS_{0},(i,r)\)\(\foralli\inS_{1},(l......
  • 2023牛客多校2
    H.0and1inBIT题意给一串操作字符串,其中包含操作\(A,B\):\(A\)代表将二进制每一位反转。\(B\)代表将二进制加\(1\)。且当二进制为全\(1\)时,二进制变为全\(0\)现在包含多次询问,每次询问给定一个区间(区间需要计算得到),给定一个初始二进制\(x\),问你二进制在经过操作字符串对......
  • 暑假补题记2
     题解:主要是对于炸弹时间的处理,直接让时间赋值给数组,进行判断即可,跑一遍bfs的板子就可以了。#include<bits/stdc++.h>#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<queue>#include<cmath>//#defineintlonglongu......