C. Sasha and a Bit of Relax
关于异或运算,你需要挖掘它的性质,否则这个题找不到规律是没办法做出来的。
$a_loplus a_{l+1} cdots oplus a_{mid} = a_{mid+1}oplus cdots oplus a_r $
则可以推出(a_loplus a_{l+1} cdots oplus a_{mid} oplus a_{mid+1}oplus cdots oplus a_r = 0)
又因为对于任意一个正整数 x 都有(x oplus 0 = x) 。所以这个题就可以冒险试一试了。
#include <bits/stdc++.h>
using namespace std;
int n;
long long has[(1<<20)+10][2];//has[x][0]表示x在偶数位出现的次数
int main(){
cin>>n;
long long num = 0,pre=0;
for(int i=1,x;i<=n;i++){
scanf("%d",&x);
has[pre][(i-1)%2]++;
pre ^= x;
num += has[pre][i%2];
}
cout<<num<<endl;
return 0;
}
但是可以稍微证明一下,为什么一段数字的异或为0,然后它们对半分就一定相等呢?
因为如果异或为0,那么这一段数字二进制表示上,每一位上面的1的个数和都为偶数个,那么我们把这段数字对半分后,这些偶数个1的拆分只能有两种情况,都为偶数,都为奇数。可见分开后的二进制位上的1的个数的奇偶性相同,即异或的结果是相同的。
D. Sasha and One More Name
首先可以想到的是,如果字符串中所有的字符都相同,或者只有一个不同,那么这个回文串是无法重构成与原串不同的回文串的。
然后我们分情况讨论:
- 长度为奇数时,我们总可以找个一对对称的位置,调换之后可以构成一个不同的回文串(满足上述条件,即存在不同的多个字符)
- 长度为偶数时,假设从中间分开之后反过来重新拼接得到t,如果前半段不是一个回文串,那么t和原串s是不同的。但是如果前半段是一个回文串呢?这意味这什么?这说明前半段和后半段是相同的,也就是说出现了循环节。由于s长度最多为5000,所以只需要从尾到头,每次只把一小部分字符挪到前面,判断是否为回文串并且不等于原串即可判断是否存在只需一刀的解。
#include <bits/stdc++.h>
using namespace std;
bool isPalindrome(const string& s) {
for(int i = 0; i < s.length(); ++i) {
if (s[i] != s[s.length() - i - 1])
return false;
}
return true;
}
bool solve1(string s) {
string t = s;
int len = s.length();
for(int i = 0; i < len; ++i) {
t = t[len-1] + t;//每次拼接一部分,从尾部拿到头部
t.resize(len);//重新调整大小
if (s != t && isPalindrome(t)) {
return true;
}
}
return false;
}
//判断是否存在多个不同字符
bool anyAnswer(const string& s) {
int nt = 0;
for(int i = 0; i < s.length(); ++i) {
nt += s[i] != s[0];
}
return nt > 1;
}
int main() {
string s;
cin >> s;
if (anyAnswer(s)) {
cout << (solve1(s) ? 1 : 2) << endl;
} else {
cout << "Impossible" << endl;
}
return 0;
}
结合着CF题解看吧,鄙人能力有限
https://codeforces.com/blog/entry/65295
G - Magic Ship
- 首先坐标范围1e9,再加上风的影响,可以知道答案会非常大,如果推公式的话,因为有风的影响发现公式很难确定。所以可以尝试二分答案。
- m为天数,可以提前将风的影响通过前缀算出来。然后其加到坐标上,只需判断该坐标与终点的曼哈顿距离是否小于等于m即可
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll X1,Y1,X2,Y2,n;
char s[100010];
ll prex[100010],prey[100010];
bool check(ll m){
ll dx = m/n*prex[n]+prex[m%n] + X1;
ll dy = m/n*prey[n]+prey[m%n] + Y1;
return abs(X2-dx)+abs(Y2-dy)<=m;
}
int main(){
cin>>X1>>Y1>>X2>>Y2>>n;
scanf("%s",s+1);
for(int i=1;i<=n;i++){
prex[i] = prex[i-1];
prey[i] = prey[i-1];
if(s[i]=='U') prey[i]++;
else if(s[i]=='D') prey[i]--;
else if(s[i]=='R') prex[i]++;
else if(s[i]=='L') prex[i]--;
}
ll l = 0,r = 1e18;
int flag = 0;
while(l<r){
ll mid = (l+r)/2;
if(check(mid)){
r = mid;
flag = 1;
}
else l = mid+1;
}
if(flag)
cout<<r<<endl;
else cout<<-1<<endl;
}