第十五次开心场
A - AAA
题意:给定一个数,分解为三个不为3的倍数且 a + b + c = n
的数
思路:简单贪心,根据情况输出 1,1,n -2
或 1,2,n-3
int main() {
// freopen("in.txt","r",stdin);
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
// for (cin >> _; _; _--) solve();
cin >> n;
if (n % 3 == 0 || n % 3 == 1)
cout << 1 << " " << 1 << " " << n - 2 << endl;
else
cout << 1 << " " << 2 << " " << n - 3 << endl;
}
B - BBB
emm,很简单
int n,a,b;
int main() {
cin >> n;
while (n--) {
cin >> x >> y;
b = max(b, y + x);
}
cout << b << endl;
}
C - CCC
C题开始的自闭路途
题意
给出n个数,记它们的gcd为g,现在询问最少去掉多少个数可以使剩下的数的gcd大于g。
思路:
想了半天,最后才知道可以暴力
先求出所有数的gcd记作gg,然后把原数组中所有的数除去这个因数gg。然后再把除去后的数组中所有的数分解质因数,用一个cnt[ ]来记录一个因数在这个除去gg的数组中共出现了几次。现在我们的目的是想让gcd增大,那么其实就是需要删掉那些在除去gg后数组中没有相同因数的数字。暴力竟然没有超时???
#include <bits/stdc++.h>
using namespace std;
const int N = 3e5 + 5, M = 1.5e7 + 5;
int n, g, ans, a[N], cc[M], np[M];
int main() {
scanf("%d", &n);
for (int i = 1; i <= n; ++i) scanf("%d", a + i), g = __gcd(a[i], g);
for (int i = 1; i <= n; ++i) ++cc[a[i] / g];
for (int i = 2; i < M; ++i) {
if (!np[i]) {
int res = 0;
for (int j = i; j < M; j += i) np[j] = 1, res += cc[j];
ans = max(ans, res);
}
}
printf("%d\n", ans ? n - ans : -1);
}
D - DDD
题意:
给你一个n个区间[l,r],问当你删掉某1个区间后,剩下的n-1个区间所能够相交的长度的最大值。
思路:
首先,我们首先考虑将所有的左括号和所有的右括号从小到大排序,那么不难发现,倘若我们需要求多个区间的相交的长度,那么我们只能选取左括号中序号最大的和右括号中最小的,他们相减即为最大长度(若为负数则为0)。
而题目中要求我们删掉某个区间,我们于是我们就可以考虑枚举被删的区间。我们可以用multiset分别存储左右括号的坐标,在枚举的过程中先删除第i个区间,统计答案之后再加上第i个区间。不断遍历更新最大值即可。
#include <bits/stdc++.h>
#define maxn 300005
using namespace std;
multiset<int>l,r;
struct Seg{
int l,r;
}q[maxn];
int main()
{
int n;
cin>>n;
for(int i=1;i<=n;i++){
scanf("%d%d",&q[i].l,&q[i].r);
l.insert(q[i].l);//用multiset存左右括号
r.insert(q[i].r);
}
int res=0;
for(int i=1;i<=n;i++){
l.erase(l.find(q[i].l));//删除第i个区间
r.erase(r.find(q[i].r));
res=max(res,*r.begin()-*--l.end());//答案是右区间的最小值和左区间的最大值
l.insert(q[i].l);
r.insert(q[i].r);
}
cout<<res<<endl;
}
E - EEE
题意:给你n个数,一个k,每两个数连接起来mod k==0的组合有多少个.
对于题目给的n规模暴力是不可能了,只能先进行预处理,然后判断是否存在即可
// Author : RioTian
// Time : 20/10/29
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 2e5 + 100;
ll n, a[N], k, ans, t;
map<ll, ll> mp[20];
int getlen(ll x) {
int cnt = 0;
for (; x; x /= 10) cnt++;
return cnt;
}
int main() {
// freopen("in.txt", "r", stdin);
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
cin >> n >> k;
for (int i = 1; i <= n; i++) {
cin >> a[i], t = a[i];
for (int j = 1; j <= 10; j++) {
t = t * 10 % k;
mp[j][t]++;
}
}
for (int i = 1; i <= n; i++) {
int len = getlen(a[i]);
ans += mp[len][(k - a[i] % k) % k], t = 1;
for (int i = 1; i <= len; i++) t = t * 10 % k;
if ((a[i] * t % k + a[i] % k) % k == 0) ans--;
}
cout << ans << endl;
}
F1
F2
https://codeforces.com/contest/1029/problem/E
虽然知道是树上问题,但一直没想到用搜索就能解决了(傻傻的推DP状态转移方程去了)
#include<bits/stdc++.h>
#define N 200000+10
using namespace std;
vector<int>g[N];
int ans,n,x,y;
int dfs(int u,int p=0)
{
int x=2;
for(int i=0;i<g[u].size();i++)
{
int v=g[u][i];
if(v!=p)
x=min(x,dfs(v,u));
}
if(u!=1&&p!=1&&x==0)
ans++;
return (x+1)%3;
}
int main()
{
cin>>n;
for(int i=1;i<n;i++)
{
cin>>x>>y;
g[x].push_back(y);
g[y].push_back(x);
}
dfs(1,0);
cout<<ans;
return 0;
}