题解与反思
仔细读题呀!!!不会的多读两遍题目
小红的素数合并
1、猜结论:举个样例猜一下结论即可。
2、呜呜呜,两个小时没看懂题,以为要合并的只剩下两个元素。题目的意思是,操作要选两个素数,两个素数相乘的结果肯定是和数,所以每个元素至多操作一次。
3、主要是分数组是奇数个元素还是偶数个,偶数比较好猜。
4、奇数个元素的话,我们俩俩乘起来,肯定有一个元素剩余,肯定剩大的元素才能缩小差距,所以奇数数个元素时最大值不参与合并。
#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
typedef long long LL;
int a[N];
int main()
{
int n;
cin >> n;
for(int i = 0; i < n; i ++)
{
cin >> a[i];
}
sort(a, a + n);
LL mi = 1e9 + 10, ma = -1e9;
for(int i = 0, j = n - 1 - (n % 2); i < n / 2; i ++, j --)
{
LL x = (LL)a[i] * a[j];
mi = min(mi, x);
ma = max(ma, x);
//cout << a[i] << endl << a[j] << endl;
}
if(n % 2)
{
mi = min(mi, (LL)a[n - 1]);
ma = max(ma, (LL)a[n - 1]);
}
cout << ma - mi << endl;
return 0;
}
D 小红的树上删边
基础的树的遍历,图论的基础太差了,要多练!!!
1、节点个数为奇数肯定不能完成
2、节点个数为偶数的时候,因为求最多删几条边,所以当子树的节点树为偶数时我们就删除盖子树与其父节点的边。
3、无向树的dfs(), 我们应该传如父节点,防止向上搜索。
#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
vector<int> g[N];
int cnt_son[N];//以i为节点的子树的节点个数
int res;
void dfs(int u, int fa)
{
cnt_son[u] = 1;
for(auto x : g[u])
{
if(x != fa)
{
dfs(x, u);
cnt_son[u] += cnt_son[x];//u为根的树的节点数等于所有子树的节点数之和
}
}
if(u != 1 && cnt_son[u] % 2 == 0) res ++;//注意根节点没有边可以删
}
int main()
{
int n;
cin >> n;
for(int i = 0; i < n - 1; i ++)
{
int x, y;
cin >> x >> y;
g[x].push_back(y);
g[y].push_back(x);
}
dfs(1, 0);
if(n % 2 == 1) cout << -1 << endl;
else cout << res << endl;
return 0;
}
E 小红的子序列求和
这题有点可惜,刚做的atcodr考了贡献法
1、分析每一位在最后答案中的贡献。
2、要会组合数的求法,n <= 1000 直接递推就行。
3、每位数字可以作为子序列中的1~K位,我们算一下其在每个位上的贡献即可。
4、计算在每个位置上的贡献的时候,要计算包含这一位的子序列有多少个,我们可以用组合数求得。
#include<bits/stdc++.h>
using namespace std;
const int mod = 1e9 + 7;
const int N = 1005;
typedef long long LL;
int C[N][N];
int qmi(int a, int k)//快速幂,用来计算10的次方
{
int res = 1;
while(k)
{
if(k & 1) res = (LL) res * a % mod;
a = (LL)a * a % mod;
k >>= 1;
}
return res;
}
int main()
{
C[0][0] = 1;
int n, k;
string s;
cin >> n >> k >> s;
for(int i = 1; i < N; i ++)
{
for(int j = 0; j <= i; j ++)
{
if(j == 0 || j == i) C[i][j] = 1;
else C[i][j] = (C[i - 1][j] + C[i - 1][j - 1]) % mod;
}
}
LL res = 0;
for(int i = 0; i < n; i ++)
{
LL x = s[i] - '0';
for(int j = 1; j <= k; j ++)
{
LL xx = qmi(10, k - j);//x在第k位的权重
LL yy = C[i][j - 1];//前面可以组合的数
LL zz = C[n - i - 1][k - j];//x后面可以组合的数
res += x * xx % mod * yy % mod * zz % mod;//贡献累加
res %= mod;
}
}
cout << res << endl;
return 0;
}