好久没更新了,弄个了小博客,有兴趣的小伙伴可以点开看看!
博客地址
AcWing第六周周赛
去掉一个元素
第一题很简单,妥妥的签到题,所以菜鸡的我只配做出签到题0.0
题目
给定一个长度为 n的整数数组 a1,a2,…,an。
请问共有多少个元素满足,在去掉该元素后,剩余元素的相加之和为一个偶数(注意,0 也算偶数)。
输入格式
第一行包含整数 n。
第二行包含 n 个整数 a1,a2,…,an。
输出格式
输出满足条件的元素个数。
数据范围
前三个测试点满足 1≤n≤11。
所有测试点满足 1≤n≤100,1≤ai≤100。
输入样例1:
1
1
输出样例1:
1
输入样例2:
10
1 2 2 3 4 4 4 2 2 2
输出样例2:
8
输入样例3:
11
2 2 2 2 2 2 2 2 2 2 99
输出样例3:
1
本人思路
确保剩下之和为偶数,则先求总和数sum,记录奇偶个数
若sum为奇数,则直接输出奇数个数
若sum为偶数,则直接输出偶数个数
因为奇数减去奇数,偶数减去偶数,结果正为偶数
代码
#include<iostream>
#include<vector>
using namespace std;
int main(){
int n;
vector<int> nums;
cin>>n;
int sum = 0;
int d = 0, s = 0;
for(int i = 0; i < n; i++){
int a;
cin>>a;
nums.push_back(a);
if(nums[i] % 2 == 0) s++;
else d++;
sum += nums[i];
}
if(sum % 2 == 0)
cout<<s<<endl;
else if(sum % 2 == 1)
cout<<d<<endl;
return 0;
}
求和
题目
用 f(x) 来表示满足下列条件的最小正整数 a:
- a≥x。
- a 的各个数位不包含除了 4 和 7 以外的其他数字。
现在,给定两个整数 l,r(l≤r),请你计算 f(l)+f(l+1)+…+f® 的值。
输入格式
一行,两个整数 l,r。
输出格式
一行,一个整数表示求得的和。
数据范围
前三个测试点满足 1≤l≤r≤10,
所有测试点满足 1≤l≤r≤10e9。
输入样例1:
2 7
输出样例1:
33
输入样例2:
7 7
输出样例2:
7
思路
把1~10e9内所有只包含4和7的数打表出来。
我也想到打表,但没想出怎么把所有符合条件的数打出来,题解是用递归打出来的,心中恍然,菜鸡完全没往这方面想。
然后在某一区间的数都记为大于该数表值,如2,3,4都记为4,则可以按区间内个数乘以表值。按输入案例1举例如下:
代码
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
typedef long long LL;
vector<LL> num;
void dfs(int n, LL x){
num.push_back(x);
if(n == 10) return ;
dfs(n + 1, x * 10 + 4);
dfs(n + 1, x * 10 + 7);
}
int main(){
dfs(0, 0);
sort(num.begin(), num.end());
LL l , r;
cin>>l >>r;
LL res = 0;
for(int i = 1; i < num.size(); i++){
LL a = num[i-1]+1, b = num[i];
res += num[i] * max(0ll, (min(r, b) - max(a, l) + 1));
}
cout<<res<<endl;
return 0;
}
构造完全图
给定一个由 n 个点和 m 条边构成的无向连通图。
我们希望通过一系列操作将其变为一个完全图(即每对不同的顶点之间都恰有一条边相连)。
每次操作时,可以选择其中一个点,找到所有和它直接相连的点,使这些点两两之间连边(若两点之间已经存在边,则无需重复连接)。
请问,至少多少次操作以后,可以将整个图变为一个完全图?
输入格式
第一行包含两个整数 n,m。
接下来 mm 行,每行包含两个整数 u,vu,v,表示点 u 和点 v 之间存在一条边。
所有点编号 1∼n。
输出格式
第一行输出最少操作次数。
第二行输出每次操作所选的点的编号,整数之间空格隔开。如果最少操作次数为 0,则无需输出第二行。
如果答案不唯一,则输出任意合理方案均可。
数据范围
前三个测试点满足 1≤n,m≤10。
所有测试点满足 1≤n≤22,0≤m≤n(n−1)2,1≤u,v≤n,u≠v。
保证没有重边和自环,保证给定图是连通的。
输入样例1:
5 6
1 2
1 3
2 3
2 5
3 4
4 5
输出样例1:
2
2 3
输入样例2:
4 4
1 2
1 3
1 4
3 4
输出样例2:
1
1
思路
大概思路就是在一个完全图里,对完全图里的点执行操作,使得不在完全图里的点合并入图中
研究了许久没有进展,以下为yxc大佬代码,已算是简单明了,奈何有些地方看不太懂,先放入留待以后破解,有厉害的大佬希望能指点一二。
代码
#include <iostream>
#include <cstring>
#include <algorithm>
#define x first
#define y second
using namespace std;
typedef pair<int, int> PII;
const int N = 22, M = 1 << N;
int n, m;
int e[N]; //初始时i点临近的所有边,以二进制形式表示,位1为有边
int f[M]; //保存状态
PII g[M]; //保存转移路径
int main()
{
cin >> n >> m;
if (m == n * (n - 1) / 2)
{
puts("0\n");
return 0;
}
for (int i = 0; i < n; i ++ ) e[i] = 1 << i;
while (m -- )
{
int a, b;
cin >> a >> b;
a --, b -- ;
e[a] |= 1 << b;
e[b] |= 1 << a;
}
memset(f, 0x3f, sizeof f);
for (int i = 0; i < n; i ++ ) f[e[i]] = 1, g[e[i]] = {0, i};
for (int i = 0; i < 1 << n; i ++ )
{
if (f[i] == 0x3f3f3f3f) continue;
for (int j = 0; j < n; j ++ )
{
if (i >> j & 1)
{
int k = i | e[j];
if (f[k] > f[i] + 1) //执行一次操作
{
f[k] = f[i] + 1;
g[k] = {i, j};
}
}
}
}
int k = (1 << n) - 1;
cout << f[k] << endl;
while (k)
{
cout << g[k].y + 1 << ' ';
k = g[k].x;
}
return 0;
}