A题 Puzzle From the Future
题目链接https://codeforces.com/contest/1474/problem/A
题意:
给出一个二进制数a,找出另一个二进制数b,使之按位以十进制的格式相加得到的c数值最大,且c没有连续相同的两位。(就是把两个只含0, 1的十进制数相加得到没有相同两位的最大数,比如a(2) = 1001,b(2) 就应该为1101,得到的c(10)为2102 )
思路:
知道题意之后就很好发现,如果a, b只由0, 1组成,那么其相加的结果c中只可能出现0,1,2三个数。
由于c相邻的两位不同,且要是最大值,不论a的首位是什么,b的首位必然是1才会使c的值最大。那么对于b的其他位,我们只需要先记录前一位c的值pre:
如果pre = 2,那c i 只能为1才能使c最大,这就取决于a i的值了,如果a i = 1, 那么b i = 0,如果a i = 0,那么b i = 1,也就是b i = a i - 1;
如果pre = 1,那 c i 可能为0,可能为2:如果a i = 1, 那b i = 1;如果a i = 0,那么b i = 0,也就是说a i = b i;
如果pre = 0,那么c i可能为1, 2,那么当a i = 1,b i = 1,a i = 0, b i = 1,也就是b i恒等于1.
AC代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e5 + 100;
int le[maxn];
int main(){
ios::sync_with_stdio(0);
cin.tie(); cout.tie(0);
int t; cin >> t;
while(t--){
int n; cin >> n;
string s; cin >> s;
int pre = s[0] - '0' + 1;
cout << 1;
for(int i = 1; i < s.length(); i ++){
if(pre == 2){
pre = 1;
cout << pre - (s[i] - '0');
}
else if(pre == 1){
pre = 2 * (s[i] - '0');
cout << s[i] - '0';
}
else {
cout << 1;
pre = s[i] - '0' + 1;
}
}
cout << "\n";
}
return 0;
}
B Different Divisors
题目链接https://codeforces.com/contest/1474/problem/B
题意:
计算出一个值a,使得a至少存在4个因子,且任意两个因子之间的差值大于等于给定的整数b,且a是在满足这个条件下的最小值。
思路:
先看示例
当b为1时,a的最小值为6(6的因子为:1,2,3,6);
当b为2时,a的最小值为15(15的因子为:1,3,5,15);
哦吼吼你是不是想到了a = (b + 1)* (b + b + 1);但是你试试b = 3?是不是就变成4 * 7 = 28,因子就变成了1,2,4,7,28了,就不满足任意两个因子的差值至少为b了。
再想以下,除了1以外,任意一个数都有两个因子:1和本身,那要找至少有四个因子的数的最小值,就找刚刚好只有四个因子的肯定比多于四个的要优,所以上面就用的是两个数相乘,那么我们只需要找到这两个数就行了。而上式出现的问题就是,b + 1或者b + b + 1可能是合数,导致求出的a的因字数大于4个且,由于多出的因子是本有的因子的因子,所以导致了任意两个因子之间不满足差值最小为b(因为本来b + 1就是踩线擦边球了,b + 1 再变成 b + 1 = c * d(c,d都不为1)的话,那abs(c - d) 肯定就小于b了呀)。所以就容易推出剩余的两个因子是素数(观察样例也发现是的),找出最小的,且>= b + 1的素数,就是二个因数,那第三个因数是不是就是>= b + b + 1的最小素数呢?不一定哦,万一第二个素数就刚好>= b + b + 1了呀,所以第三个因子应该是大于第二个因子的最小素数。
在本题中,由于b的范围很小,所以直接暴力求素数就可以了。
那么答案就是第二、三个因子的乘积就是了。因为res = 因子 2 * 因子 3,那么res 的因子就又四个,分别为1,因子 2,因子 3,res。
AC代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e5 + 100;
int le[maxn];
bool isPrime(int a){
for(int i = 2; i <= sqrt(a); i ++){
if(a % i == 0) return false;
}
return true;
}
int main(){
ios::sync_with_stdio(0);
cin.tie(); cout.tie(0);
int t; cin >> t;
while(t--){
int d; cin >> d;
int a = 1 + d, b = 1 + 2 * d;
while(!isPrime(a)) a ++;
b = a + d;
while(!isPrime(b)) b ++;
cout << 1ll * a * b << "\n";
}
return 0;
}
C Array Destruction
题目链接https://codeforces.com/contest/1474/problem/C
题意:
给出一个长度为2n的数组,判断数组内的任意三个数是否满足a + b = c,若满足,删除a,b;再判断数组内是否存在另外的两个数是否满足d + e = max(a, b),若满足,就删除d,e;一直循环做这个操作,直到数组内的数字被删除完毕为止并输出最初的c和之后两个数的组合即(a, b);(c, d)…(最初提到的c就是第一组a, b的和而已)
所以这个题就和明确了,每次找到当前数组的最大值,然后找到一个值与之匹配相加,如果其和等于上一个匹配的最大值,则继续匹配,一直匹配到数组