部分题解(A、C、G、H)
A 阿宁的签到题
送分题,不放代码了
C 阿宁的大背包
思路:
背包顺序我的想法是
大的数尽量往中间放,因为他们能被加更多次。同理小的数往两边放。
大概就是135......642这样(最左边放一个数,最右边放一个数,循环往复)
循环里面记得取余就行
代码:
#include <iostream>
using namespace std;
int main() {
int n, k=0;
long long int res = 0, a[1005], b[1005];
cin>>n;
for(int i=0;i<n;i++){
if(i%2==0){
a[k++]=i+1;
}else{
a[n-k]=i+1;
}
}
for(int i=0;i<n;i++){
b[i] = a[i];
}
for(int i=0;i<n;i++){
for(int j=0;j<n-i-1;j++){
a[j]=a[j]+a[j+1];
a[j]%=1000000007;
}
}
cout<<a[0]<<endl;
for(int i=0;i<n;i++){
cout<<b[i]<<" ";
}
}
G 阿宁的整数配对
思路:
要考虑负数/自然数个数是奇数偶数的情况(全是负数或自然数就直接算)
我的想法是
先sort排序
再两两相乘,到了负数与自然数交界处判断一下情况是否要扔掉一个数(保证最大的两个正数能够相乘)
然后两两相乘的值算好放到新数组
再sort一下输出k个就好
负数与自然数个数情况判断
1.负数-奇数,自然数-奇数
从头到后两两相乘算就行
2.负数-奇数,自然数-偶数
负数两两相乘算(多出的最大的负数扔掉不管),自然数两两相乘算
3.负数-偶数,自然数-奇数/偶数
负数两两相乘算,自然数两两相乘算(多出的最小的自然数扔掉不管)
当然也可以换种思路(我的代码思路)
总数偶数个,从头到后两两相乘算就行
总数奇数个,就要去掉中间的一个数
负数-奇数,去掉最大的负数
自然数-奇数,去掉最小的自然数
代码:
#include <bits/stdc++.h>
using namespace std;
int main() {
int n, k, a[200005], b[100005], l = 0, m = 0, flag = 0;
long long int res = 0;
cin >> n >> k ;
for (int i = 0 ; i < n ; i ++) {
cin >> a[i] ;
if (a[i] < 0) {
l++;
}
}
sort(a, a + n);
if (l > 0) {
for (int i = 0 ; i < n && i + 1 < n ; i += 2) {
if (flag == 0 && a[i + 1] >= 0) {
if ((n - i - 1) % 2 == 0) {
i++;
}
flag = 1;
}
b[m] = a[i] * a[i + 1];
m ++;
}
} else {
for (int i = n - 1 ; i >= 0 ; i -= 2) {
b[m] = a[i] * a[i - 1];
m++;
}
}
sort(b, b + m);
for (int i = m - 1 ; k > 0 ; i --, k --) {
res += b[i];
}
cout << res;
}
H 阿宁讨伐虚空
思路:
三种情况(一定能攻击到,完全不能攻击到,可能攻击到)
完全不能攻击到是x<l
一定能攻击到是x>r(x==r时只是可能攻击到,要注意)
可能攻击到算一下就行,记得浮点数处理
代码:
#include <iostream>
using namespace std;
int main() {
long long int x, l, r;
double res;
cin >> x;
cin >> l >> r;
if(x<=l){
res = 0;
}else if(x>r){
res = 1;
}else{
res = (x-l) * 1.0 / (r-l+1);
}
cout << res;
}