寒假挣扎一下Google Code Jam Kickstart

对于技术面试慌的丫匹,所以做做CJK。

Kickstart Round H 2018

Problem A. Big Buttons

题意:构造一个只由“B”、“R”组成的长度为N的字符串,需要满足条件:不能出现输入的前缀。求有多少种字符串。

思路:只由“B”、“R”组成的长度为n的字符串共有2 ^ N种,减去含有禁止前缀的字符串即可。后者的计算,将字符串排序后,从最后一个字符串开始,向前找第一个它的前缀,如果找不到的话,将2 ^ len加到结果里。

代码:

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<map>
#include<cmath>
#include<string>
#include<vector>
#include<set>
#include<queue>
#include<stack>
#include<iostream>
#include<algorithm>
using namespace std;
 
#define debug(x) cout << #x << " = " << x << endl
#define lowbit(x) (x & (-x))
 
typedef long long LL;
typedef pair<int, int>PII;
const int maxn = 1e5 + 10;
const int inf = 0xfffffff;
const double pi = acos(-1);
string s[105], t[105];
int cnt = 0;
LL qwe (LL x,LL y){
	LL t = 1;
	while (y){
		if (y%2!=0)
			t = t * x;
		y /= 2;
		x = x * x;
	}
	return t;
}
 
bool check(string sp, string ss)
{
	if(sp.length() > ss.length()) return false;
	if(ss.substr(0, sp.length()) == sp) return true;
	return false;
}
 
inline void open(string s){
	freopen((s + ".in").c_str(), "r", stdin);
	freopen((s + ".out").c_str(), "w", stdout);
}
 
int main()
{
	open("A-large-practice");
	int T, n, p;
	scanf("%d", &T);
	for(int cas = 1; cas <= T; cas++)
	{
		printf("Case #%d: ", cas);
		scanf("%d%d", &n, &p);
		for(int i = 1; i <= p; i++) cin >> s[i];
		cnt = 0;
		sort(s + 1, s + 1 + p);
		LL sum = qwe(2, n);
		for(int i = p; i >= 1; i--)
		{
			int flag = 0;
			for(int j = i - 1; j >= 1; j--)
			{
				if(check(s[j], s[i])) 
				{
					flag = 1;
					break;
				}
			}
			if(!flag) sum -= qwe(2, n - s[i].length());
		}
		printf("%lld\n", sum);
	}
	return 0;
}

Problem B. Mural

题意:一面墙由N个部分组成,每一部分有对应的美丽值,给一个部分涂刷后就能拥有这个部分的美丽值。每天早上可以涂刷一个部分,必须接着以前涂刷过的部分,晚上会有洪水毁坏一个在两边并且没有被涂刷的部分,求能保证的最大美丽值。

思路:维护一个长度为⌈n / 2⌉的子序列的最大和。

代码:

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<map>
#include<cmath>
#include<string>
#include<vector>
#include<set>
#include<queue>
#include<stack>
#include<iostream>
#include<algorithm>
using namespace std;

#define debug(x) cout << #x << " = " << x << endl
#define lowbit(x) (x & (-x))

typedef long long LL;
typedef pair<int, int>PII;
const int maxn = 5e6 + 10;
const int inf = 0xfffffff;
const double pi = acos(-1);
char s[maxn];
int a[maxn];

inline void open(string s){
	freopen((s + ".in").c_str(), "r", stdin);
	freopen((s + ".out").c_str(), "w", stdout);
}

int main()
{
	open("B-large-practice");
	int T, n;
	scanf("%d", &T);
	for(int cas = 1; cas <= T; cas++)
	{
		scanf("%d", &n);
		scanf("%s", s + 1);
		int len = n / 2;
		if(n % 2) len++;
		int l = 1, r = 0, sum = 0, Max = 0;
		while(r <= n)
		{
			if(r - l + 1 < len)
			{
				r++;
				sum += (s[r] - '0');
			}
			else
			{
				Max = max(Max, sum);
				sum -= (s[l] - '0');
				l++;
			}
		}
		printf("Case #%d: %d\n", cas, Max);
	}
	return 0;
}

Problem C. Let Me Count The Ways

题意:2N个人,其中有m对新婚夫妻,他们一坐在一起就会给对方写爱情诗不划船(被我一jio踹下水!!),问有多少种安排方式使得没有一对新婚夫妻是坐在一起的。

思路:容斥的思想。

           没有1对坐在一起的安排方式 = 总的安排方式 (2N)!  -  至少有一对夫妻坐在一起的安排方式

           

           

                                                                故计算公式为:

代码:

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<map>
#include<cmath>
#include<string>
#include<vector>
#include<set>
#include<queue>
#include<stack>
#include<iostream>
#include<algorithm>
using namespace std;

#define debug(x) cout << #x << " = " << x << endl
#define lowbit(x) (x & (-x))

typedef long long LL;
typedef pair<int, int>PII;
const int maxn = 2e5 + 10;
const int inf = 0xfffffff;
const int mod = 1e9 + 7;
const double pi = acos(-1);

inline void open(string s){
	freopen((s + ".in").c_str(), "r", stdin);
	freopen((s + ".out").c_str(), "w", stdout);
}

LL j[maxn + 5], nj[maxn + 5], g[maxn + 5], jc[maxn + 5];
LL poww(LL x, LL y)
{
    LL ans = 1ll;
    while(y > 0){
        if(y & 1) ans = ans * x % mod;
        y >>= 1;
        x = x * x % mod;
    }
    return ans;
}

LL C(LL x, LL y){
    if(x < y) return 0;
    LL ans = 1ll;
    ans = j[x] * nj[y] % mod * nj[x - y] % mod;
    return ans;
}

void Init(){
    j[1] = 1ll; j[0] = nj[0] = 1;
    for(LL i = 2; i <= maxn; i++){
        j[i] = j[i - 1] * i % mod;
    }
    nj[maxn] = poww(j[maxn], mod - 2) % mod;
    for(LL i = maxn - 1; i >= 1; i--){
        nj[i] = nj[i + 1] * (i + 1) % mod;
    }
    jc[0] = 1;
    for(int i = 1; i < maxn; i++) jc[i] = ((jc[i - 1] * i) % mod);
}

int main()
{
	open("C-large-practice");
	Init();
	int T, n, m;
	scanf("%d", &T);
	for(int cas = 1; cas <= T; cas++)
	{
		scanf("%d%d", &n, &m);
		LL ans = 0;
		for(int i = 0; i <= m; i++)
		{
			g[i] = ((((C(m, i) * jc[2 * n - i]) % mod) * poww(2, i)) % mod);
			if(i % 2) ans = ((ans + mod - g[i]) % mod);
			else ans = ((ans + g[i]) % mod);
		}
		printf("Case #%d: %lld\n", cas, ans);
	}	
	return 0;
}

 

Kickstart Round G 2018

Problem A. Product Triplets

题意:给出N个数,求至少满足以下三个条件中的一个的三元组(x, y, z)有多少个,其中1 <= x < y < z <= N。

  • Ax = Ay × Az, and/or
  • Ay = Ax × Az, and/or
  • Az = Ax × Ay

思路:把数组排个序,枚举较小的两个数X和Y,二分查找在Y后面(包括值等于Y的数)值为X * Y的数有几个。

代码:

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<map>
#include<cmath>
#include<string>
#include<vector>
#include<set>
#include<queue>
#include<stack>
#include<iostream>
#include<algorithm>
using namespace std;

#define debug(x) cout << #x << " = " << x << endl
#define lowbit(x) (x & (-x))

typedef long long LL;
typedef pair<int, int>PII;
const int maxn = 1e5 + 10;
const int mod = 1e9 + 7;
const double pi = acos(-1);
LL a[maxn];

inline void open(string s)
{
	freopen((s + ".in").c_str(), "r", stdin);
	freopen((s + ".out").c_str(), "w", stdout);
}

int main()
{
	open("A-large-practice");
	int T, n;
	scanf("%d", &T);
	for(int cas = 1; cas <= T; cas++)
	{
		LL sum = 0;
		scanf("%d", &n);
		for(int i = 1; i <= n; i++) scanf("%lld", &a[i]);
		sort(a + 1, a + 1 + n);
		for(int i = 1; i <= n - 2; i++)
		{
			for(int j = i + 1; j <= n - 1; j++)
			{
				LL res = a[i] * a[j];
				if(a[i] == 0 && a[j] == 0) sum += (n - j);
				else
				{
					int pos1 = lower_bound(a + j + 1, a + n + 1, res) - a;
					int pos2 = upper_bound(a + j + 1, a + n + 1, res) - a;
					if(res == a[pos1]) sum += pos2 - pos1;
				}
			}
		}
		printf("Case #%d: %lld\n", cas, sum);
	}
	return 0;
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值