集训预备队选拔day2

第二天的选拔赛,简单了一些=-=

A序列划分-codeforces1197C
将非递减的序列划分成k段,使最右减最左的和最小。
和这种序列差值有关的,用差分来写,就转化成和的问题。

B转移矩阵-POJ3070
就是个模板题

#include<iostream>
#include<cstring>
using namespace std;
const int MAX = 10;
#define ll long long
class Matrix {
public:
	Matrix(int r, int c) :row(r), col(c) {}
	void Init()
	{
		memset(map, 0, sizeof(map));
		map[0][0] = map[0][1] = map[1][0] = 1;
	}
	void Unit() //初始化为单位矩阵 
	{
		memset(map, 0, sizeof(map));
		for (int i = 0; i < row; i++)
			map[i][i] = 1;
	}
	int Result() const { return map[0][1] % 10000; }
	friend Matrix operator*(const Matrix&, const Matrix&);
	int Pow(int);
private:
	__int64 map[MAX][MAX];
	int row, col;
};
Matrix operator*(const Matrix& M1, const Matrix& M2) 
{
	Matrix M(M1.row, M2.col);  
	for (int i = 0; i < M1.row; i++)
		for (int j = 0; j < M2.col; j++)
		{
			M.map[i][j] = 0;
			for (int k = 0; k < M1.col; k++)
				M.map[i][j] += M1.map[i][k] * M2.map[k][j];
			M.map[i][j] %= 10000;
		}
	return M;
}
Matrix M(2, 2);
int Matrix::Pow(int n) 
{
	Matrix temp(2, 2);
	temp.Init();
	for (int i = 0; (1<<i) <= n; i++)
	{
		if ((1<<i)&n) M = M * temp;
		temp = temp * temp;
	}
	return M.Result();
}
int main()
{
	ll num;
	while (cin >> num&&num != -1)
	{
		M.Unit();
		cout << M.Pow(num) << endl;
	}
	return 0;
}

C思维-codeforces797C
感觉思维题,就是贪心,或者由事件的终点来直接推断结果。(个人的一点想法…)
所以这题就是一个贪心,不难,但很容易写错…wa了一个多小时Q-Q

D模拟-OpenJ_Bailian3709
就是个模拟,签到题

#include<iostream>
#include<stdio.h>
#include<algorithm>
#include<string>
using namespace std;
#define ll long long
int main()
{
	//freopen("in.txt", "r", stdin);
	int n;
	scanf("%d", &n);
	string temp, ans;
	ll tt = 0;
	while (n--) {
		cin >> temp;
		ans.clear();
		int size = temp.size();
		for (int i = 0; i < size; i++) {//2->10
			tt <<= 1;
			tt += temp[i] - '0';
		}
		while (tt) {//10->3
			ans.insert(ans.begin(),tt % 3 + '0');
			tt /= 3;
		}
		cout << ans << "\n";
	}
}

E最近公共车站-codeforces832D
树上LCA
三个点,两两求LCA,值异或,求出三个点的汇点。(为什么这样能求汇点呢,画图看看就知道了)

G生日序列-HDU4027
线段树,注意当数变为1的时候就不用更新了,因此维护一个最大值的树,是1的时候就不用向下更新。
和codeforces有题挺像的哈

#include<iostream>
#include<stdio.h>
#include<algorithm>
#include<cstring>
#include<map>
#include<cmath>
using namespace std;
#define ll long long
const int maxn = 100005;
const int N = 1 << 63;
ll maxx[maxn << 2];
ll sum[maxn << 2];
void pushup(int rt)
{
	sum[rt] = sum[rt << 1] + sum[rt << 1 | 1];
	maxx[rt] = max(maxx[rt << 1], maxx[rt << 1 | 1]);
}
void build(int l, int r, int rt)
{
	if (l == r)
	{
		scanf("%lld", &sum[rt]);
		maxx[rt] = sum[rt];
		return;
	}
	int m = (l + r) >> 1;
	build(l, m, rt << 1);
	build(m + 1, r, rt << 1 | 1);
	pushup(rt);
}
void update(int L, int R, int l, int r, int rt)
{
	if (maxx[rt] <= 1)return;
	if (l == r)
	{
		sum[rt] = (ll)sqrt(1.0*sum[rt]);
		maxx[rt] = sum[rt];
		return;
	}
	int m = (l + r) >> 1;
	if (L <= m)update(L, R, l, m, rt << 1);
	if (m < R) update(L, R, m + 1, r, rt << 1 | 1);
	pushup(rt);
}
ll query(int L, int R, int l, int r, int rt)
{
	if (L <= l && r <= R)
		return sum[rt];
	int m = (l + r) >> 1;
	ll ret = 0;
	if (L <= m) ret += query(L, R, l, m, rt << 1);
	if (m < R)  ret += query(L, R, m + 1, r, rt << 1 | 1);
	return ret;
}
int main()
{
	//freopen("in.txt", "r", stdin);
	int n;
	int cc = 1;
	while (scanf("%d", &n) != EOF) {
		printf("Case #%d:\n", cc++);
		build(1, n, 1);
		int m;
		scanf("%d", &m);
		while (m--) {
			int op;
			scanf("%d", &op);
			if (op == 0) {//update
				int l, r;
				scanf("%d%d", &l, &r);
				if (l > r) {
					int temp = l;
					l = r;
					r = temp;
				}
				update(l, r, 1, n, 1);
			}
			else {//sum
				int l, r;
				scanf("%d%d", &l, &r);
				if (l > r) {
					int temp = l;
					l = r;
					r = temp;
				}
				printf("%lld\n", query(l, r, 1, n, 1));
			}
		}
		printf("\n");
	}
}

H超神学院-POJ1703
种类并查集/带权边,我更习惯用带权边来写。

#include<iostream>
#include<stdio.h>
#include<cstring>
using namespace std;
int pre[100005];
int sum[100005];
int FindLeft(int n) {
	if (n == pre[n])
		return n;
	int r;
	r = FindLeft(pre[n]);
	sum[n] += sum[pre[n]];
	pre[n] = r;
	return r;
}
void Link(int i, int j, int s) {
	int Prei, Prej;
	Prei = FindLeft(i);
	Prej = FindLeft(j);
	if (Prei < Prej) {
		sum[Prej] = s + sum[i] - sum[j];
		pre[Prej] = Prei;
	}
	else {
		sum[Prei] = sum[j] - s - sum[i];
		pre[Prei] = Prej;
	}
}
int main()
{
	//freopen("in.txt","r",stdin);
	//freopen("out.txt","w",stdout);
	int t;
	scanf("%d", &t);
	while (t--) {
		int n, m;
		scanf("%d%d", &n, &m);
		memset(sum, 0, sizeof(sum));
		for (int i = 0; i <= n; i++)
			pre[i] = i;
		while (m--) {
			char op;
			int a, b;
			getchar();
			scanf("%c %d %d", &op, &a, &b);
			if (op == 'D')Link(a, b, 1);
			else {
				if (FindLeft(a) == FindLeft(b)) {
					if ((sum[b] - sum[a]) & 1)printf("In different gangs.\n");
					else
						printf("In the same gang.\n");
				}
				else {
					printf("Not sure yet.\n");
				}
			}
		}
	}
}

I打表题-LightOj-2370
欧拉函数打表题。以前好像写过。
不是打欧拉函数的表,应该也打不下,是打素数的表,因为要满足欧拉函数值尽可能大,且数值尽可能小数,肯定就是素数(在素数an右边an+1左边的合数b,b的欧拉函数值小于等于an的欧拉函数值)

#include<iostream>
#include<stdio.h>
#include<cstring>
using namespace std;
#define ll long long
const int maxn = 1e6+5;
int prime[maxn];
void init() {//初始化,看这个数是不是素数
	memset(prime, 0, sizeof(prime));
	prime[0] = prime[1] = 1;
	for (int i = 2; i < maxn; i++) {
		if (!prime[i]) {
			for (int j = i + i; j <= maxn; j += i)prime[j] = 1;
		}
	}
}
int main()
{
	init();
	int t;
	scanf("%d", &t);
	int cnt = 1;
	while (t--) {
		ll ans = 0;
		int n;
		scanf("%d", &n);
		while (n--) {
			int temp;
			scanf("%d", &temp);
			for (int i = temp + 1;; i++) {
				if (prime[i] == 0) {
					ans += i;
					break;
				}
			}
		}
		printf("Case %d: %lld Xukha\n", cnt++, ans);
	}
}

J T-shirts Codeforces1000A
就是模拟,没了。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值