第十五次开心场

A - AAA

CodeForces - 1047A

A

题意:给定一个数,分解为三个不为3的倍数且 a + b + c = n 的数

思路:简单贪心,根据情况输出 1,1,n -21,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

CodeForces - 1047B

B

emm,很简单

int n,a,b;
int main() {
    cin >> n;
    while (n--) {
        cin >> x >> y;
        b = max(b, y + x);
    }
    cout << b << endl;
}

C - CCC

CodeForces - 1047C

C题开始的自闭路途

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

CodeForces - 1029C

D

题意:

给你一个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

CodeForces - 1029D

E

题意:给你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

CodeForces - 1029A

F1

F2

https://codeforces.com/contest/1029/problem/E

F2

虽然知道是树上问题,但一直没想到用搜索就能解决了(傻傻的推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;
}
posted @ 2020-10-30 15:42  RioTian  阅读(61)  评论(0编辑  收藏  举报