CF691

A. Fashion in Berland

思路

对于一个扣子特判, 剩下的必须有且仅有一个开着。

代码

#include<bits/stdc++.h>

using namespace std;

int n;
int a[1010];
int main()
{
	cin >> n;
	for(int i = 1; i <= n; i++)
	{
		cin >> a[i];
	}
	if(n == 1)
	{
		if(a[1] == 0)
		{
			printf("NO\n");
		}
		else
		{
			printf("YES\n");
		}
		return 0;
	}
	int cnt = 0;
	for(int i = 1;  i <= n; i++)
	{
		if(a[i] == 0)
		{
			cnt++;
			if(cnt > 1)
			{
				break;
			}
		}
	}
	if(cnt != 1)
	{
		printf("NO\n");
	}
	else
	{
		printf("YES\n");
	}
	return 0;
}

dalao

可以全加起来判断啊。。。
我(蒟蒻):。。。。我好菜啊

/*
Do you see the way that tree bends? Does it inspire?
Leaning out to catch the sun's rays...a lesson to be applied...
Are you gettin' something out of this all encompassing trip?
You can spend your time alone redigesting past regrets oh...
Or you can come to terms and realize
You're the only one who can forgive yourself oh yeah...
Makes much more sense to live in the present tense...
Have you ideas on how this life ends?
Checked your hands and studied the lines?
Have you the belief that the road ahead ascends off into the light?
Seems that needlessly it's gettin' harder
To find an approach and a way to live...
Are we gettin' something out of this all-encompassing trip?
You can spend your time alone redigesting past regrets, oh...
Or you can come to terms and realize...
You're the only one who cannot forgive yourself, oh...
A-makes much more sense to live in the present tense...
*/

//#pragma comment(linker, "/STACK:16777216")
#define _CRT_SECURE_NO_WARNINGS

#include <fstream>
#include <iostream>
#include <string>
#include <complex>
#include <math.h>
#include <set>
#include <vector>
#include <map>
#include <queue>
#include <stdio.h>
#include <stack>
#include <algorithm>
#include <list>
#include <ctime>
#include <memory.h>
#include <assert.h>

#define y0 sdkfaslhagaklsldk
#define y1 aasdfasdfasdf
#define yn askfhwqriuperikldjk
#define j1 assdgsdgasghsf
#define tm sdfjahlfasfh
#define lr asgasgash
#define norm asdfasdgasdgsd

#define eps 1e-9
#define M_PI 3.141592653589793
#define bs 1000000007
#define bsize 350

using namespace std;

const int INF = 1e9;
const int N = 100031;

int n, ar[N], s;

int main(){
	//freopen("fabro.in","r",stdin);
	//freopen("fabro.out","w",stdout);
	//freopen("F:/in.txt", "r", stdin);
	//freopen("F:/output.txt", "w", stdout);
	//ios_base::sync_with_stdio(0);
	//cin.tie(0);

	cin >> n;
	for (int i = 1; i <= n; i++)
	{
		cin >> ar[i];
		s += ar[i];
	}
	--n;
	if (n == 0)
		n = 1;

	if (s == n)
		cout << "YES" << endl;
	else
		cout << "NO" << endl;

	cin.get(); cin.get();
	return 0;
}

B. s-palindrome

思路

如果一个字符串是关于中心对称的, 那么首先串中对称位置的字符都是对称的, 所以我们就可以想到首先把有对称字符的字符集它的对称字符用(map)存。然后对于根除的字符串判断即可。
怎么判断字符对称字符, 。。。额。。。。题目上有图;

代码

#include<bits/stdc++.h>

using namespace std;

map<char, char> mp;
char s[100010];
int main()
{
	mp['A'] = 'A';
	mp['b'] = 'd';
	mp['d'] = 'b';
	mp['H'] = 'H';
	mp['I'] = 'I';
	mp['M'] = 'M';
	mp['O'] = 'O';
	mp['o'] = 'o';
	mp['p'] = 'q';
	mp['q'] = 'p';
	mp['T'] = 'T';
	mp['U'] = 'U';
	mp['V'] = 'V';
	mp['v'] = 'v';
	mp['W'] = 'W';
	mp['w'] = 'w';
	mp['X'] = 'X';
	mp['x'] = 'x';
	mp['Y'] = 'Y';
	scanf("%s", s+1);
	int n = strlen(s+1);
	int len = n;
	if(n % 2 == 0)
	{
		n = n / 2;
	}
	else
	{
		n = n / 2 + 1;
	}
	for(int i = 1; i <= n; i++)
	{
		if(mp[s[i]] != s[len-i+1])
		{
			printf("NIE\n");
			return 0; 
		}
	}
	printf("TAK\n"); 
	return 0;
}

dalao

可以用set存, 然后直接两个一头一尾的指针同时向中间维护不就好了。。。, 根本不用搞什么len-i+1啦
我:(蒟蒻*2)。。。。。。。。。。

#include <cstdio>
#include <iostream>
#include <vector>
#include <string>
#include <set>
#include <algorithm>
using namespace std;

typedef pair <char, char> cc;

set <cc> S;
string s;

int main()
{
	S.insert(cc('A', 'A'));
	S.insert(cc('b', 'd'));
	S.insert(cc('d', 'b'));
	S.insert(cc('H', 'H'));
	S.insert(cc('I', 'I'));
	S.insert(cc('M', 'M'));
	S.insert(cc('O', 'O'));
	S.insert(cc('o', 'o'));
	S.insert(cc('p', 'q'));
	S.insert(cc('q', 'p'));
	S.insert(cc('T', 'T'));
	S.insert(cc('U', 'U'));
	S.insert(cc('V', 'V'));
	S.insert(cc('v', 'v'));
	S.insert(cc('W', 'W'));
	S.insert(cc('w', 'w'));
	S.insert(cc('X', 'X'));
	S.insert(cc('x', 'x'));
	S.insert(cc('Y', 'Y'));
	cin >> s;
	int l = 0, r = s.length() - 1;
	while (l <= r) {
		if (S.find(cc(s[l], s[r])) == S.end()) break;
		l++; r--;
	}
	printf("%s\n", l <= r? "NIE": "TAK");
	return 0;
}

C. Exponential notation

思路

主要分这么几步。
1.找小数点位置, 并区分整数和小数, 并去掉前导零, 和小数点后的后置零。
2.算指数;
3.然后再去一边前导0, 最后再输出。
具体细节看代码的, (又臭又长还有一堆调试)。。。。。

代码

#include<bits/stdc++.h>

using namespace std;

char s[1000010];
int high = -1;
string zong;
int pos = 0;
int main()
{
	int cnt = 0;
	scanf("%s", s+1);
	int len = strlen(s+1);
	pos = len+1;
	int st = 1;
	while(s[st] == '0' && s[st] != '.')
	{
		st++;
	}
	bool is_have = false;
	bool is_zheng = false;
	int mid = 0; 
	int end = len;
	//cout << st << endl;
	for(int i = st; i <= len; i++)
	{
		if(s[i] == '.')
		{
			pos = i;
			if(i != len)
			{
				is_have = true;
				mid = i + 1;
				
			}
			break;
		}
		char ch = s[i];
		if(high == -1)
		{
			high = i;
		}
		zong[cnt++] = ch;
		is_zheng = true;
	}
	if(is_have)
	{
		//cout << end << endl;
		//printf("ok\n");
		while(s[end] == '0')
		{
			//cout << end << endl;
			end--;
		}
		if(is_zheng == false)
		{
			while(s[mid] == '0')
			{
				mid++;
			}
		}
		//cout << end << endl;
		for(int i = mid; i <= end; i++)
		{
			char ch = s[i];
			if(high == -1)
			{
				high = i;
			}
			zong[cnt++] = ch;
		}
	}
	int zhishu;
	if(high < pos)
	{
		pos--;
		zhishu = pos - high;
	}
	else
	{
		zhishu = pos - high;
	}
	/*for(int i = 0; i < cnt; i++)
	{
		cout << zong[i];
	}
	cout << endl;*/
	end = cnt-1;
	/*cout << end << endl;
	for(int i = 0; i <= end; i++)
	{
		cout << zong[i];
	}*/
	//cout << end << endl;
	while(zong[end] == '0' && end >= 1)
	{
		end--;
	}
	//cout << high << endl << pos << endl;
	cout << zong[0];
	if(end != 0)
	{
		cout << '.';
	}
	for(int i = 1; i <= end; i++)
	{
		cout << zong[i];
	}
	if(zhishu != 0)
	{
		printf("E%d", zhishu);
	}
	return 0;
}

dalao

既然你说的这么烂, 那就我来吧。
首先一个while找到小数点位置, 如果没有, 那么在后面添上。
然后将字符串反转, 从后往前删掉前导0.
再将字符串正到原来的位置, 并去掉后置0
然后从前往后找小数点位置, 并把他之前遍历过几个数记下来。
如果他之前遍历过0个数, 那么就说明它小于1.
所以我们越过小数点, 删掉前导0, 最终剩下的那个整数变成只有一位整数的小数, 并算出指数来(负数)。
否则, 首先删掉小数点, 并把小数点移到第一个数位后面, 接着处理后置0, 然后再算指数输出即可, 如果为整数, 那么就不输出小数点即可。
我(蒟蒻):大佬果然强。%%%%%%%%%%%%%%%%

/*
When you feel the world is above you
When you feel like screaming your lungs out

When you're in the darkness all alone
Don't wanna let it eat you alive
You'll never be alone, you'll never be alone
A man's gotta do what he's gotta do as long as you

Shout, scream your hearts out
Don't let nobody take you down
Where you ain't belong

Shout, scream your hearts out
Don't let nobody take you down
Where you ain't belong, yeah

Why don't you fight for once in your life?
Don't wanna live your life through someone else's eyes
You'll never be alone, you'll never be alone
A man's gotta do what he's gotta do as long as you

Shout, scream your hearts out
Don't let nobody take you down
Where you ain't belong

Shout, scream your hearts out
Don't let nobody take you down
Where you ain't belong, yeah

Now that I'm here, I'm gonna face my fears
Tired of hiding and I'm tired of running
All that was part of me the fear that was in me
I'm strong enough to finally break free

Shout, scream your hearts out
Don't let nobody take you down
Where you ain't belong

Shout, scream your hearts out
Don't let nobody take you down
Where you ain't belong, yeah

It's your time to shout
So shout, it's your time to shout, yeah
*/

//#pragma comment(linker, "/STACK:16777216")
#define _CRT_SECURE_NO_WARNINGS

#include <fstream>
#include <iostream>
#include <string>
#include <complex>
#include <math.h>
#include <set>
#include <vector>
#include <map>
#include <queue>
#include <stdio.h>
#include <stack>
#include <algorithm>
#include <list>
#include <ctime>
#include <memory.h>
#include <assert.h>

#define y0 sdkfaslhagaklsldk
#define y1 aasdfasdfasdf
#define yn askfhwqriuperikldjk
#define j1 assdgsdgasghsf
#define tm sdfjahlfasfh
#define lr asgasgash
#define norm asdfasdgasdgsd

#define eps 1e-9
#define M_PI 3.141592653589793
#define bs 1000000007
#define bsize 350

using namespace std;

const int INF = 1e9;
const int N = 100031;

string st;

int main(){
	//freopen("fabro.in","r",stdin);
	//freopen("fabro.out","w",stdout);
	//freopen("F:/in.txt", "r", stdin);
	//freopen("F:/output.txt", "w", stdout);
	ios_base::sync_with_stdio(0);
	//cin.tie(0);

	getline(cin, st);
	int p = 0;
	while (p < st.size() && st[p] != '.')
		++p;
	if (p == st.size())
		st += ".";

	reverse(st.begin(), st.end());
	while (st[st.size() - 1] == '0')
		st.erase(st.end() - 1);

	reverse(st.begin(), st.end());
	while (st[st.size() - 1] == '0')
		st.erase(st.end() - 1);

	int oh = 0;
	for (int i = 0; i < st.size(); i++)
	{
		if (st[i] != '.')
			oh++;
		else
			break;
	}

	if (oh == 0) // <1
	{
		int q = 1;
		int xp = 0;
		while (st[q] == '0')
		{
			++q;
			++xp;
		}
		cout << st[q];
		if (q + 1 < st.size())
		{
			cout << ".";
		}
		for (int i = q + 1; i < st.size(); i++)
		{
			cout << st[i];
		}
		++xp;
		cout << "E-" << xp << endl;
	}
	else
	{
		st.erase(st.begin() + oh);
		cout << st[0];
		while (st.size() > 1 && st[st.size() - 1] == '0')
			st.erase(st.end() - 1);
		if (st.size()>1)
		{
			cout << ".";
		}
		for (int i = 1; i < st.size(); i++)
		{
			cout << st[i];
		}
		--oh;
		if (oh>0)
			cout << "E" << oh << endl;
	}

		cin.get(); cin.get();
	return 0;
}

D. Swaps in Permutation

思路

考虑这样一个图;

1
2
3
4
5
6
7

那么, 很容易看出, 这个图1, 4, 7可以轻易交换, 既然要字典序最大, 不妨直接倒叙, 也就是7,4,1.
由此可以得出一个结论, 一个相连的连通块其实可以相乘任意一种顺序(因为能够交换无数次)
所以, 我们就可以让每个连通块都倒叙。
然后输出整个序列即可。
可以用并查集维护, 可惜, 玄学T掉(菜就是菜)

代码

#include<bits/stdc++.h>

using namespace std;

int n, m;
int p[1000010];
priority_queue<int> pq[1000010];
int f[1000010];
int find(int x)
{
	return f[x] == x ? x : find(f[x]);
}
int main()
{
	scanf("%d %d", &n, &m);
	for(int i = 1; i <= n; i++)
	{
		cin >> p[i];
		f[i] = i;
	}
	for(int i = 1; i <= m; i++)
	{
		int ai, bi;
		scanf("%d %d", &ai, &bi);
		f[find(ai)] = find(bi);
	}
	for(int i = 1; i <= n; i++)
	{
		pq[find(i)].push(p[i]);
	}
	for(int i = 1; i <= n; i++)
	{
		printf("%d ", pq[find(i)].top());
		pq[find(i)].pop();
	}
	cout << endl;
	return 0;
}

dalao

直接用vector存一下, 每个连通块排一下序, 然后统一一下答案即可。
为什么不T呢, 因为我是大佬啊, 哈哈哈哈哈
我(蒟蒻):呜呜呜呜呜呜我好菜。。。。

/*
Don't even think about reachin' me
'Cause I won't be home
Don't even think about stoppin' by
Don't think of me at all

I did, what I had to do
And if there was a reason, it was you

Don't even think about gettin' inside
Voices in my head, voices
I got scratches, all over my arms
One for each day, since I fell apart

I did, what I had to do
And if there was a reason, it was you, oh

Footsteps in the hole, it was you, you
Oh oh
Pictures on my chest, it was you, it was you

I did, what I had to do and if there was a reason
There wasn't no reason, no
And if, there's something you'd like to do
Oh just let me continue, to blame you, oh oh

Footsteps in the hole, it was you, you
Oh oh
Pictures on my chest, it was you, it was you
*/

//#pragma comment(linker, "/STACK:16777216")
#define _CRT_SECURE_NO_WARNINGS

#include <fstream>
#include <iostream>
#include <string>
#include <complex>
#include <math.h>
#include <set>
#include <vector>
#include <map>
#include <queue>
#include <stdio.h>
#include <stack>
#include <algorithm>
#include <list>
#include <ctime>
#include <memory.h>
#include <assert.h>

#define y0 sdkfaslhagaklsldk
#define y1 aasdfasdfasdf
#define yn askfhwqriuperikldjk
#define j1 assdgsdgasghsf
#define tm sdfjahlfasfh
#define lr asgasgash
#define norm asdfasdgasdgsd

#define eps 1e-9
#define M_PI 3.141592653589793
#define bs 1000000007
#define bsize 350

using namespace std;

const int INF = 1e9;
const int N = 1000031;

int n, k, ar[N];
vector<int> vec[N];
int w[N];

int get(int x)
{
	if (w[x] == x)
		return x;
	return w[x] = get(w[x]);
}

void merge(int a, int b)
{
	a = get(a);
	b = get(b);
	w[a] = b;
}

int ans[N];

int main(){
	//freopen("fabro.in","r",stdin);
	//freopen("fabro.out","w",stdout);
	//freopen("F:/in.txt", "r", stdin);
	//freopen("F:/output.txt", "w", stdout);
	ios_base::sync_with_stdio(0);
	//cin.tie(0);

	cin >> n >> k;
	for (int i = 1; i <= n; i++)
	{
		cin >> ar[i];
	}

	for (int i = 1; i <= n; i++)
		w[i] = i;

	for (int i = 1; i <= k; i++)
	{
		int a, b;
		cin >> a >> b;
		merge(a, b);
	}

	for (int i = 1; i <= n; i++)
	{
		int id = get(i);
		vec[id].push_back(ar[i]);
	}

	for (int i = 1; i <= n; i++)
		sort(vec[i].begin(), vec[i].end());

	for (int i = 1; i <= n; i++)
	{
		int id = get(i);
		int val = vec[id].back();
		vec[id].pop_back();
		ans[i] = val;
	}

	for (int i = 1; i <= n; i++)
	{
		if (i > 1)
			cout << " ";
		cout << ans[i];
	}
	cout << endl;

	cin.get(); cin.get();
	return 0;
}

E. Xor-sequences

菜鸡的我肯定独立做不出这道毒瘤题, 看了题解自己写了写代码, 真是菜的透彻, 彻底。

思路

z i , j z_{i, j} zi,j表示长度为i的序列结尾为 a i , j a_{i, j} ai,j, 设 g i , j g_{i, j} gi,j表示i, j两个数是否能满足异或为1的数%3 = 0, 满足为1, 不满足为0;
那么, 很容易得到状态转移方程 z i , j = ∑ k = 1 n z i − 1 , k ⋅ g k , j z_{i,j} = \sum_{k = 1}^{n}z_{i-1,k}\cdot g_{k, j} zi,j=k=1nzi1,kgk,j
总的来说, 这个东西可以用矩阵乘法优化, 因为里面是两个向量乘积。
所以,我们设矩阵 G = [ g i , j ] G = [g_{i,j}] G=[gi,j] Z i = [ z i , j ] Z_i = [z_{i,j}] Zi=[zi,j], 那么最终答案为 Z k Z_k Zk元素和, 且 Z i × G = Z i + 1 Z_i\times G=Z_{i+1} Zi×G=Zi+1
初始时 Z 0 = [ 1 ] Z_0 = [1] Z0=[1], 快速幂即可。

代码

#include<bits/stdc++.h>

using namespace std;
typedef long long ll;
const ll mod = 1e9 + 7;

int n;
ll k;
ll a[110];
struct matrix
{
	int r, c;
	ll z[110][110];
	matrix(){}
	void init()
	{
		r = 0;
		c = 0;
		memset(z, 0, sizeof(z));	
	}
}G, Z, ans;
matrix operator*(matrix x, matrix y)
{
	matrix res;
	res.init(); 
	res.r = x.r;
	res.c = y.c;
	for(int i = 1; i <= res.r; i++)
	{
		for(int j = 1; j <= res.c; j++)
		{
			for(int k = 1; k <= x.c; k++)
			{
				res.z[i][j] = (res.z[i][j] + x.z[i][k] * y.z[k][j] % mod) % mod;
			}
		}
	}
	return res;
}
ll lowbit(ll x)
{
	return x & (-x);
}
ll calc(ll x)
{
	ll res = 0;
    while(x)
	{
       x ^= lowbit(x);
       res++;
    }
    return res;
}
matrix quick_pow(matrix x, ll y)
{
	matrix res;
	res.init();
	res.r = n;
	res.c = n;
	for(int i = 1; i <= n; i++)
	{
		res.z[i][i] = 1;
	}
	while(y)
	{
		if(y & 1)
		{
			res = res * x;
		}
		y >>= 1;
		x = x * x;
	}
    return res;
}
int main()
{
	G.init();
	cin >> n >> k;
	G.r = n;
	G.c = n;
	for(int i = 1; i <= n; i++)
	{
		cin >> a[i];
	}
	for(int i = 1; i <= n; i++)
	{
		for(int j = 1; j <= n; j++)
		{
			ll now = (a[i] ^ a[j]); 
			if(calc(now) % 3 == 0)
			{
				G.z[i][j] = 1ll;
			}
		}
	}
	/*for(int i = 1; i <= n; i++)
	{
		for(int j = 1; j <= n; j++)
		{
			cout << G.z[i][j] << " ";
		}
		cout << endl;
	}*/
	ans.init();
	ans = quick_pow(G, k-1);
	ll res = 0;
	/*for(int i = 1; i <= n; i++)
	{
		for(int j = 1; j <= n; j++)
		{
			cout << G.z[i][j] << " ";
		}
		cout << endl;
	}*/
	for(int i = 1; i <= n; i++)
	{
		for(int j = 1; j <= n; j++)
		{
			res = (res + ans.z[i][j]) % mod;
		}
	}
	cout << res << endl;
	return 0;
}

dalao

都看题解了我tm有什么好说的。。。
我:遭受到了攻击QAQ~

F: 太菜没过。。<^ - ^>

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值