2018年牛客多校算法寒假训练营练习比赛(第三场)

一个小问题
链接:https://ac.nowcoder.com/acm/contest/12138/B
来源:牛客网

题目描述
uu遇到了一个小问题,可是他不想答。你能替他解决这个问题吗?
问题:给你k对a和r是否存在一个正整数x使每队a和r都满足:x mod a=r,求最小正解x或无解。

输入描述:
第一行是正整数k(k<=100000)
接下来k行,每行有俩个正整数a,r(100000>a>r>=0)
输出描述:
在每个测试用例输出非负整数m,占一行。
如果有多个可能的值,输出最小的值。
如果没有可能的值,则输出-1。
示例1
输入
复制
2
8 7
11 9
输出
复制
31

在这里插入图片描述

中国剩余定理的详细推导

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <set>
#include <string>
#include <queue>
#include <map>
#include <stack>
#include <map>
#include <unordered_map>
#include <vector>
#include <cmath>
//#include <ext/rope>
#include <bits/stdc++.h> 

using namespace std;
using namespace __gnu_cxx;

#define gt(x) x = read()
#define int long long
#define ios ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
#define endl "\n"
//#define x first
//#define y second

int dx[4] = {0, 1, 0, -1};
int dy[4] = {1, 0, -1, 0}; 

//typedef __int128 INT;
typedef pair<double, int> PDI;
typedef pair<int, int> PII;
typedef unsigned long long ULL;

inline int read(int out = 0)
{
    char c;
    while((c=getchar()) < 48 || c > 57);
    while(c >= 48 && c <= 57) out=out*10+c-48,c=getchar();
    return out; 
}

const int N = 1e4 + 10;
const int M = N * 10;
const long long mod = 998244353;
const int PP = 131;
const int inf = 0x3f3f3f3f;
const int INF = 0x3f3f3f3f3f3f3f3f;
const double eps = 1e-10;
const double PI = acos(-1);

int exgcd(int a, int b, int &x, int &y){
	if (!b){
		x = 1;
		y = 0;
		return a;
	}
	
	int d = exgcd(b, a % b, y, x);
	y -= a / b * x;
	return d;
}

signed main(){
	int n;
	scanf("%lld", &n);
	
	int a, r;
	scanf("%lld%lld", &a, &r);
	
	bool flag = false;
	for (int i = 1; i < n; i ++){
		int a1, r1;
		scanf("%lld%lld", &a1, &r1);
		int x, y;
		int d = exgcd(a, a1, x, y);
		if ((r1 - r) % d){
			flag = true;
		}
		else{
			int tp = a1 / d;
			int n1 = (((r1 - r) / d * x % tp) + tp) % tp;
		    r = (n1 % tp) * a + r; 
		    a = a * tp;
		}
	}
	
	if (flag)   cout << "-1" << endl;
	else{
		cout << (r % a + a) % a << endl;
	}
	
	return 0;
}

小牛vs小客
链接:https://ac.nowcoder.com/acm/contest/12138/D
来源:牛客网

题目描述
小牛和小客玩石子游戏,他们用n个石子围成一圈,小牛和小客分别从其中取石子,谁先取完谁胜,每次可以从一圈中取一个或者相邻两个,每次都是小牛先取,请输出胜利者的名字(小牛获胜输出XiaoNiu,小客获胜输出XiaoKe)(1 2 3 4 取走 2 13 不算相邻)

输入描述:
输入包括多组测试数据
每组测试数据一个n(1≤n≤1e9)
输出描述:
每组用一行输出胜利者的名字(小牛获胜输出XiaoNiu,小客获胜输出XiaoKe)
示例1
输入
复制
2
3
输出
复制
XiaoNiu
XiaoKe

博弈的精髓是预判,博弈的精髓时到达自己有益的一方,博弈的精髓是以对方对待自己的方式对待对方,博弈的精髓是最后一击,博弈的精髓是让对方处于必败态,博弈的精髓是都是精明的,博弈的精髓是一击不错,每次取对称的,最后一击即可

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <set>
#include <string>
#include <queue>
#include <map>
#include <stack>
#include <map>
#include <unordered_map>
#include <vector>
#include <cmath>
#include <ext/rope>
//#include <bits/stdc++.h> 

using namespace std;
using namespace __gnu_cxx;

#define gt(x) x = read()
#define int long long
#define ios ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
#define endl "\n"
//#define x first
//#define y second

int dx[4] = {0, 1, 0, -1};
int dy[4] = {1, 0, -1, 0}; 

//typedef __int128 INT;
typedef pair<double, int> PDI;
typedef pair<int, int> PII;
typedef unsigned long long ULL;

inline int read(int out = 0)
{
    char c;
    while((c=getchar()) < 48 || c > 57);
    while(c >= 48 && c <= 57) out=out*10+c-48,c=getchar();
    return out; 
}

const int N = 1e7 + 10;
const int M = N * 10;
const long long mod = 998244353;
const int PP = 131;
const int inf = 0x3f3f3f3f;
const int INF = 0x3f3f3f3f3f3f3f3f;
const double eps = 1e-10;
const double PI = acos(-1);

signed main(){
	int n;
	while(~scanf("%lld", &n)){
		if (n < 3){
			cout << "XiaoNiu" << endl;
		}
		else  cout << "XiaoKe" << endl;
 	}
	
	return 0;
}

进击吧!阶乘
链接:https://ac.nowcoder.com/acm/contest/12138/E
来源:牛客网

题目描述
给定一个整数N(0≤N≤10000),求取N的阶乘
输入描述:
多个测试数据,每个测试数据输入一个数N
输出描述:
每组用一行输出N的阶乘
示例1
输入
复制
1
2
3
输出
复制
1
2
6

高精度乘法的模板

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <set>
#include <string>
#include <queue>
#include <map>
#include <stack>
#include <map>
#include <unordered_map>
#include <vector>
#include <cmath>
#include <ext/rope>
//#include <bits/stdc++.h> 

using namespace std;
using namespace __gnu_cxx;

#define gt(x) x = read()
#define int long long
#define ios ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
#define endl "\n"
//#define x first
//#define y second

int dx[4] = {0, 1, 0, -1};
int dy[4] = {1, 0, -1, 0}; 

//typedef __int128 INT;
typedef pair<double, int> PDI;
typedef pair<int, int> PII;
typedef unsigned long long ULL;

inline int read(int out = 0)
{
    char c;
    while((c=getchar()) < 48 || c > 57);
    while(c >= 48 && c <= 57) out=out*10+c-48,c=getchar();
    return out; 
}

const int N = 1e4 + 10;
const int M = N * 10;
const long long mod = 998244353;
const int PP = 131;
const int inf = 0x3f3f3f3f;
const int INF = 0x3f3f3f3f3f3f3f3f;
const double eps = 1e-10;
const double PI = acos(-1);

vector<int> mul(vector<int> &A, int b)
{
    vector<int> C;

    int t = 0;
    for (int i = 0; i < A.size() || t; i ++ )
    {
        if (i < A.size()) t += A[i] * b;
        C.push_back(t % 10);
        t /= 10;
    }

    while (C.size() > 1 && C.back() == 0) C.pop_back();

    return C;
}

signed main(){
	//vector<int> A;
	
	int n;
	while(~scanf("%lld", &n)){
		if (n == 0)   cout << "0" << endl;
		else if (n == 1)   cout << "1" << endl;
		else {
			vector<int> v;
			v.push_back(1);
			for (int i = 2; i <= n; i ++){
				v = mul(v, i);
			}
			
			for (int i = v.size() - 1; i >= 0; i --)    cout << v[i];
			cout << endl;
		}
 	}
	
	return 0;
}

小牛再战
链接:https://ac.nowcoder.com/acm/contest/12138/F
来源:牛客网

题目描述
共有N堆石子,已知每堆中石子的数量,两个人轮流取石子,每次只能选择N堆石子中的一堆取一定数量的石子(最少取一个),取过子之后,还可以将该堆石子中剩余的石子随意选取几个放到其它的任意一堆或几堆上。等哪个人无法取子时就表示此人输掉了游戏。注意:一堆石子没有子之后,就不能再往此处放石子了。

假设每次都是小牛先取石子,并且游戏双方都绝对聪明,现在给你石子的堆数、每堆石子的数量,请判断出小牛能否获胜。

输入描述:
可能有多组测试数据(测试数据组数不超过1000)
每组测试数据的第一行是一个整数,表示N(1<=N<=10)
第二行是N个整数分别表示该堆石子中石子的数量。(每堆石子数目不超过100)
当输入的N为0时,表示输入结束
输出描述:
对于每组测试数据,输出Win表示小牛可以获胜,输出Lose表示小牛必然会败。
示例1
输入
复制
3
2 1 3
2
1 1
0
输出
复制
Win
Lose
备注:
提示:
例如:如果最开始有4堆石子,石子个数分别为3 1 4 2,而小牛想决定要先拿走第三堆石子中的两个石子(石子堆状态变为3 1 2 2),然后他可以使石子堆达到的状态有以下几种:
3 1 2 2(不再移动石子)
4 1 1 2(移动到第一堆一个)
3 2 1 2(移动到第二堆一个)
3 1 1 3(移动到第四堆一个)
5 1 0 2(全部移动到第一堆)
3 3 0 2(全部移动到第二堆)
3 1 0 4(全部移动到最后)

特判加sg函数

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <set>
#include <string>
#include <queue>
#include <map>
#include <stack>
#include <map>
#include <unordered_map>
#include <vector>
#include <cmath>
//#include <ext/rope>
#include <bits/stdc++.h> 

using namespace std;
using namespace __gnu_cxx;

#define gt(x) x = read()
#define int long long
#define ios ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
#define endl "\n"
//#define x first
//#define y second

int dx[4] = {0, 1, 0, -1};
int dy[4] = {1, 0, -1, 0}; 

//typedef __int128 INT;
typedef pair<double, int> PDI;
typedef pair<int, int> PII;
typedef unsigned long long ULL;

inline int read(int out = 0)
{
    char c;
    while((c=getchar()) < 48 || c > 57);
    while(c >= 48 && c <= 57) out=out*10+c-48,c=getchar();
    return out; 
}

const int N = 1e4 + 10;
const int M = N * 10;
const long long mod = 998244353;
const int PP = 131;
const int inf = 0x3f3f3f3f;
const int INF = 0x3f3f3f3f3f3f3f3f;
const double eps = 1e-10;
const double PI = acos(-1);

int f[110];
int a[110];

int sg(int x){
	if (f[x] != -1)   return f[x];
	
	unordered_set<int> S;
	for (int i = 1; i <= x; i ++){
		S.insert(x - i);
	}
	
	for (int i = 0; ; i ++)
		if (!S.count(i))
		   return f[x] = i;
}

signed main(){
	int n;
	while(~scanf("%lld", &n)){
		if (n == 0)    break;
		memset(f, -1, sizeof f);
		
		int res = 0;
		for (int i = 1; i <= n; i ++){
			scanf("%lld", &a[i]);
		}
		
		for (int i = 1; i <= n; i ++){
			res ^= sg(a[i]);
		}
		
		if (res)   cout << "Win" << endl;
		else   cout << "Lose" << endl;
	}
	
	return 0;
}

大水题
链接:https://ac.nowcoder.com/acm/contest/12138/G
来源:牛客网

题目描述
给出一个数n,求1到n中,有多少个数不是2 5 11 13的倍数。
输入描述:
本题有多组输入
每行一个数n,1<=n<=10^18.
输出描述:
每行输出输出不是2 5 11 13的倍数的数共有多少。
示例1
输入
复制
15
输出
复制
4
说明
1 3 7 9

容斥原理

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <set>
#include <string>
#include <queue>
#include <map>
#include <stack>
#include <map>
#include <unordered_map>
#include <vector>
#include <cmath>
#include <ext/rope>
//#include <bits/stdc++.h> 

using namespace std;
using namespace __gnu_cxx;

#define gt(x) x = read()
#define int long long
#define ios ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
#define endl "\n"
//#define x first
//#define y second

int dx[4] = {0, 1, 0, -1};
int dy[4] = {1, 0, -1, 0}; 

//typedef __int128 INT;
typedef pair<double, int> PDI;
typedef pair<int, int> PII;
typedef unsigned long long ULL;

inline int read(int out = 0)
{
    char c;
    while((c=getchar()) < 48 || c > 57);
    while(c >= 48 && c <= 57) out=out*10+c-48,c=getchar();
    return out; 
}

const int N = 1e4 + 10;
const int M = N * 10;
const long long mod = 998244353;
const int PP = 131;
const int inf = 0x3f3f3f3f;
const int INF = 0x3f3f3f3f3f3f3f3f;
const double eps = 1e-10;
const double PI = acos(-1);

int p[] = {2, 5, 11, 13};

signed main(){
	int n;
	while(~scanf("%lld", &n)){
		int cnt = 0;
		for (int i = 1; i < 1 << 4ll; i ++){
			int t = 1, s = 0;
			for (int j = 0; j < 4ll; j ++){
				if (i >> j & 1){
					if (t * p[j] > n){
						t = -1;
						break;
					}
					t *= p[j];
					s ++;
				}
			}
			
			if (t != -1){
				if (s % 2){
					cnt += (n / t);
				}
				else cnt -= (n / t);
			}
		}
		
		cout << n - cnt << endl;
	}
	
	return 0;
}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值