A 不断减损的时间
题目链接:A-不断减损的时间_2023牛客寒假算法基础集训营3 (nowcoder.com)
输入:
4
1 2 -3 4
输出:
0
思路:注意到数据范围包括了负数,如果要使得所有元素之和最小的话,那么所有正偶数都要除到变成奇数,副偶数不动,再将所有的数加起来。
代码:
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N = 1e5 + 5;
int a[N];
int32_t main(){
ios::sync_with_stdio(0);
cin.tie(0);
int tt = 1;
//cin >> tt;
while(tt--){
int n; cin >> n;
int ans = 0;
for(int i = 1; i <= n; i++){
cin >> a[i];
if(a[i] % 2 == 0 && a[i] > 0){
while(a[i] != 0 && a[i] % 2 == 0){
a[i] /= 2;
}
}
ans += a[i];
}
printf("%lld\n", ans);
}
}
B 勉强拼凑的记忆
题目链接:B-勉强拼凑的记忆_2023牛客寒假算法基础集训营3 (nowcoder.com)
输入:
3
2
4
6
输出:
-1
2
4
题意:给一个n,要求用n块1 * x的积木搭成一个正方形,其中1<=x<=(n + 1)/2,问正方形的边长最大为多少,搭不了的话就输出-1。
思路1:为了堆出更大的正方形,尽可能多的使用1 * ((n + 1) / 2)的长方形,可以采用样例说明堆的方法。于是判断能不能堆成的方法分成两部分:
1.当边长x小于等于(n + 1) / 2的时候,即积木只需要从上到下一个个摆放即可,这时候只需要判断积木个数是否小于n就好了。
2.当边长x大于(n + 1) / 2的时候,右边需要摆放积木来补充,首先摆成x * ((n + 1) / 2)的形状,补充成x * x还需要(x - (n + 1) / 2) 个1 * ((n + 1) / 2)的长方形和x - (n + 1) / 2个1 * (x - (n + 1) / 2))的长方形,检查数量是否小于等于n即可。
用二分的方法找出最大的边长
代码:
#include<bits/stdc++.h>
#define int long long
using namespace std;
int n, a;
bool check(int x){
if(x > a) return x + 2 * (x - a) <= n;
else return x <= n;
}
int32_t main(){
ios::sync_with_stdio(0);
cin.tie(0);
int tt; cin >> tt;
while(tt--){
cin >> n;
a = (n + 1) / 2;
if(n == 2) printf("-1\n");
else{
int l = 1, r = n;
while(l <= r){
int mid = (l + r) / 2;
if(check(mid)) l = mid + 1;
else r = mid - 1;
}
printf("%lld\n", r);
}
}
}
C忽远忽近的距离
题目链接:C-忽远忽近的距离_2023牛客寒假算法基础集训营3 (nowcoder.com)
输入:
4
输出:
3 4 1 2
思路:很显然n小于4和n等于7的都输出-1,有三种方式可以构造:
-
长度为4,如:3 4 1 2。
-
长度为5,如:3 4 5 1 2。
-
长度为6,如:3 4 5 1 2 3。
所以如果n%4等于3,那么就构造5+6,如果n%4等于2,那么构造一个6,如果n%4等于1,那么构造一个5,剩下全部构造4。
代码:
#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 5;
int a[N], flag = 0;
int main(){
ios::sync_with_stdio(0);
cin.tie(0);
int tt = 1;
while(tt--){
int n; cin >> n;
if(n <= 3 || n == 7) printf("-1\n");
else{
int yu = n % 4;
int num4 = n / 4, num5 = (yu == 1 || yu == 3), num6 = (yu == 2 || yu == 3);
num4 -= (num5 + num6);
int i = 1;
for(; i <= n && num4; i += 4){
printf("%d %d %d %d ", i + 2, i + 3, i, i + 1);
num4--;
}
if(num5--){
printf("%d %d %d %d %d ", i + 2, i + 3,i + 4, i, i + 1);
i += 5;
}
if(num6--){
printf("%d %d %d %d %d %d", i + 3, i + 4,i + 5, i, i + 1, i + 2);
i += 6;
}
}
}
}
D宿命之间的对决
题目链接:D-宿命之间的对决_2023牛客寒假算法基础集训营3 (nowcoder.com)
输入:
2
输出:
kou
思路:参考链接https://www.cnblogs.com/BlankYang/p/17066469.html
-
若n是奇数,那么因子只有奇数,奇数-奇数为偶数,而小红是先手,只有奇数可以选,所以小红和操作完,n是偶数,当小紫操作时,小紫可以选择将偶数减去一个偶数变成偶数,也可以减去一个奇数变成一个奇数,对于小紫来说,最好的情况就是变成奇数,避免了自己减到0,所以n是奇数时,小紫必胜。
-
若n时偶数,可以由n是奇数时推出小红必胜。
代码:
#include<bits/stdc++.h>
#define int long long
using namespace std;
int32_t main(){
ios::sync_with_stdio(0);
cin.tie(0);
int tt = 1;
// cin >> tt;
while(tt--){
int n; cin >> n;
if(n % 2 == 0) printf("kou\n");
else printf("yukari\n");
}
}
E公平守望的灯塔
题目链接:E-公平守望的灯塔_2023牛客寒假算法基础集训营3 (nowcoder.com)
输入:
1 0 0 1
输出:
0 0
题意:给出A、B点,要求找出一个整点C,满足ABC是一个以AB为斜边的等腰直角三角形
思路1:可以看出C只有可能是两个点,即圆与AB的中垂线的交点,假设向量OA为(x,y),那么旋转90°的向量OC就是(-y,x)或者(y,-x),点O求出来后,点C就可以求出来了。
代码:
#include<bits/stdc++.h>
#define int long long
using namespace std;
bool check(double a){ //检查是否为整数
if(abs(a - (int)a) > 0.0000001) return false;
return true;
}
signed main(){
double xa, ya, xb, yb; cin >> xa >> ya >> xb >> yb;
double mx = (xa + xb) / 2.0, my = (ya + yb) / 2.0;
double dx = xa - mx, dy = ya - my;
double ansx = dy + mx, ansy = -dx + my;
if(check(ansx) && check(ansy)) printf("%lld %lld", (int)ansx, (int)ansy);
else{
ansx = -dy + mx, ansy = dx + my;
if(check(ansx) && check(ansy)) printf("%lld %lld", (int)ansx, (int)ansy);
else printf("No Answer!\n");
}
}
F迎接终结的寂灭
题目链接:F-迎接终结的寂灭_2023牛客寒假算法基础集训营3 (nowcoder.com)
思路:输出42即可,代码我都懒得放。
G严肃古板的秩序
题目链接:G-严肃古板的秩序_2023牛客寒假算法基础集训营3 (nowcoder.com)
输入1:
2?1?2?2=3
输出1:
2-1#2+2=3
输入2:
5?2=2
输出2:
-1
输入3:
5?8=13
输出3:
5+8=13
题意:给一个只有数字和问号的字符串,问能否填上'+', '-', '#'使得等式成立,a#b表示a的a次方对b取模,优先级和+-一样 。
思路1:三进制枚举,只有12个?,每个问号枚举三种情况,总共枚举=531,441次,在时间范围内
代码:
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N = 1e2 + 5;
int a[N], mk;
char op[N];
int ksm(int x, int y, int mod){
int res = 1ll;
while(y){
if(y % 2) res = res * x % mod;
x = x * x % mod;
y >>= 1ll;
}
return res % mod;
}
int32_t main(){
ios::sync_with_stdio(0);
cin.tie(0);
int ans = 0, num, flag = 1;
char ope;
while(cin >> num >> ope){
a[mk++] = num;
if(ope == '=') break;
}
cin >> ans;
int g = pow(3, mk - 1);
for(int i = 0; i < g; i++){
int p = i;
for(int t = 1; t < mk; t++){
if(p % 3 == 0) op[t] = '+';
else if(p % 3 == 1) op[t] = '-';
else op[t] = '#';
p /= 3;
}
int sum = a[0];
for(int j = 1; j < mk; j++){
if(op[j] == '+') sum += a[j];
else if(op[j] == '-') sum -= a[j];
else{
if(sum <= 0 || a[j] <= 0){ //非负整数包括0,正整数不包括0
sum = -1;
break;
}
sum = ksm(sum % a[j], sum, a[j]); //取模的话,底数可以取模,指数不能取模
}
}
if(sum == ans){
printf("%lld", a[0]);
for(int j = 1; j < mk; j++){
printf("%c%lld", op[j], a[j]);
}
printf("=%lld", ans);
flag = 0;
break;
}
}
if(flag) printf("-1\n");
}