Codeforces Round #615 (Div. 3)

传送门

A Collecting Coins
B Collecting Packages
C Product of Three Numbers
D MEX maximizing
E - Obtain a Permutation

A Collecting Coins

题意:有3孩子,分別有a,b,c个糖果,现有n个糖果给他们,最后能否让三个人拥有的糖果数量相同。

思路:找出糖果最多的孩子,先让三个孩子的糖果数量都等于最多的那个,然后看是否能平分剩下的,注意糖果数量可能不够三个孩子的糖果数量都等于最多的那个的情况。
#include <bits/stdc++.h>
using namespace std;
template<class T> inline void read(T &x){
	x=0; char c=getchar(); int f=1;
	while (!isdigit(c)) {if (c=='-') f=-1; c=getchar();}
	while (isdigit(c)) {x=x*10+c-'0'; c=getchar();} x*=f;
}

void solve()
{
    int a, b, c, n;
    scanf("%d%d%d%d", &a, &b, &c, &n);
    int ans, ma = max({a, b, c});
    ans = 3*ma-a-b-c;
    (ans<=n&&(n-ans)%3==0)?puts("YES"):puts("NO");
}
int main()
{
    int t;
    read(t);
    while(t--)
        solve();
    return 0;
}

B Collecting Packages

题意:机器人在(0,0)点,它只能向上和向右走。现给n个点,问它能不能走完,能就输出YES和路径,否则输出NO

思路:把点按照x小的优先,x相同y小优先的顺序排列好。如果可以的话这个顺序就是机器人的路线,不可以就输出NO。注意(0,0)也是一个点。

tips:这里我用的是vector来存点,也可以结构体,基本无差别。auto是万能变量,比较方便,但得用c++11以上编译器才能通过。

#include <bits/stdc++.h>
#define debug(x) cout <<#x<<" = "<<x<<endl
#define gg cout <<"-------------QAQ---------------"<<endl
#define fi first
#define se second
#define pb push_back
#define ll long long
using namespace std;
typedef vector<int> Vi;
template<class T> inline void read(T &x){
	x=0; char c=getchar(); int f=1;
	while (!isdigit(c)) {if (c=='-') f=-1; c=getchar();}
	while (isdigit(c)) {x=x*10+c-'0'; c=getchar();} x*=f;
}
const int N = 266666;
void FAST(){ios::sync_with_stdio(false);cin.tie(0);}

bool cmp(pii x, pii y)
{
    if(x.fi==y.fi) return x.se<y.se;
    return x.fi<y.fi;
}
void solve()
{
    int n;
    read(n);
    vector<pii> a(n+10);
    for(int i = 0; i < n; ++i) scanf("%d%d", &a[i].fi, &a[i].se);
    a[n].fi = a[n].se = 0;
    sort(a.begin(), a.begin()+n+1, cmp);
    vector<pii> ans;
    for(int i = 1; i <= n; ++i) {
        int x, y;
        x = a[i].fi-a[i-1].fi;
        y = a[i].se-a[i-1].se;
        if(x<0||y<0) {
            puts("NO"); return;
        }
        ans.pb(pii(x, y));
    }
    puts("YES");
    for(auto x:ans) {
        while(x.fi--) putchar('R');
        while(x.se--) putchar('U');
    }
    printf("\n");
}
int main()
{
    int t;
    read(t);
    while(t--)
        solve();
    return 0;
}

C Product of Three Numbers

题意:给一个n,问是否存在a,b,c三个大于等于2且都不想用的数相乘等n,abc=n&&min({a,b,c})>=2

思路:找出所有素数因子,如果素数因子数小于3直接输出NO,素数因子是升序的。让a等于第一个因子,先让b等于第二个因子,然后判断a,b是否相等,如果相等a继续乘下一个因子。此时如果没有因子也输出NO,否则剩下的因子全给c,最后判断a,b和c是否相等即可。
#include <bits/stdc++.h>
#define debug(x) cout <<#x<<" = "<<x<<endl
#define gg cout <<"-------------QAQ---------------"<<endl
#define fi first
#define se second
#define pb push_back
#define ll long long

using namespace std;
typedef pair<int,int> pii;
typedef vector<int> Vi;
template<class T> inline void read(T &x){
	x=0; char c=getchar(); int f=1;
	while (!isdigit(c)) {if (c=='-') f=-1; c=getchar();}
	while (isdigit(c)) {x=x*10+c-'0'; c=getchar();} x*=f;
}

void solve()
{
    int n;
    read(n);
    vector<int> ans; //用来放因子
    int t = n;
    for(int i = 2; i*i <= n; ++i) {
        while(t%i == 0) {
            ans.pb(i); t /= i;
        }
    }
    if(t > 1) ans.pb(t);
    if(ans.size()<3) {  //因子数小于三就是NO
        puts("NO"); return;
    }
    int a,b,c;
    a=ans[0];
    b=ans[1];
    int l = 2;
    while(a == b) {
        b*=ans[l];
        l++;
        if(l == ans.size()) {
            puts("NO"); return;
        }
    }
    c=1;
    for(int i = l; i < ans.size();++i) c*=ans[i];//剩余因子全部给c
    if(a==c||b==c) {
        puts("NO"); return;
    }
    puts("YES");
    printf("%d %d %d\n", a, b, c);
}
int main()
{
    int t;
    read(t);
    while(t--)
        solve();
    return 0;
}

D MEX maximizing

题意:定义一个东西:数组的价值是不为数组元素的最大整数。还定义数组内的元素可以加减任意的x(不能小于0),先想数组里添加q个元素,求最大价值。

思路:我们发现1和1+kx在数组里是等价的,也就是说我们可以先把ai%x的个数记录下来。此时数组里元素只有0到x-1。我们可以把这些元素按层来放置,如果元素t次数大于i,那就在第i层有这个元素,我们发现最小的元素没有满的那一层与答案相关,且那一层缺少的最小元素就是我们所需答案对x取模。答案就是层数*x+元素。我们求的也就是0到x-1最小次数,如果有多个找最小的值。
我用的是set的一个自定义排序方法,直接放进set就行。注意先把0到x-1的0次放入set,每次操作时,把输入元素次数+1放入set,元素次数也要删除。
#include <bits/stdc++.h>
#define debug(x) cout <<#x<<" = "<<x<<endl
#define gg cout <<"-------------QAQ---------------"<<endl
#define fi first
#define se second
#define pb push_back
#define SZ(x) ((int)x.size())
#define ll long long
using namespace std;
typedef unsigned int ui;
typedef pair<int,int> pii;
 
struct node
{
    int x, cnt;
    node(){}
    node(int _x, int _cnt) {
        x = _x, cnt = _cnt;
    }
};
struct cmp
{
    bool operator()(const node& a, const node& b) {
        if(a.cnt == b.cnt) return a.x < b.x;
        return a.cnt < b.cnt;
    }
};
set<node, cmp> s;
map<int, int> num;
int main()
{
    int t, x;
    scanf("%d%d", &t, &x);
    for(int i = 0; i < x; ++i) s.insert(node(i,0));
    while(t--) {
        int temp;
        scanf("%d",&temp);
        num[temp%x]++;
        s.insert(node(temp%x, num[temp%x]));
        s.erase(node(temp%x, num[temp%x]-1));
        auto tt = s.begin();
//        debug(tt->x);
//        debug(tt->cnt);
        printf("%d\n", (tt->cnt)*x+tt->x);
    }
    return 0;
}

当然D题也可以用线段树来维护,不推荐,我试着玩

#include <bits/stdc++.h>
#define debug(x) cout <<#x<<" = "<<x<<endl
#define gg cout <<"-------------QAQ---------------"<<endl
#define fi first
#define se second
#define pb push_back
#define lson l, m, rt<<1
#define rson m+1, r, rt<<1|1
using namespace std;
const int N = 4066666;
void FAST(){ios::sync_with_stdio(false);cin.tie(0);}

struct node {
    int x, cnt;
    node(){}
    node(int _x, int _cnt) {
        x = _x, cnt = _cnt;
    }
};
node MIN[N];
map<int, int> num;
node min(node x, node y)
{
    if(x.cnt == y.cnt) {
        if(x.x < y.x) return x;
        return y;
    }
    if(x.cnt < y.cnt) return x;
    return y;
}
void build(int l, int r, int rt)
{
    if(l == r) {
        MIN[rt].cnt = 0;
        MIN[rt].x = l;
        return ;
    }
    int m = (l+r)>>1;
    build(lson);
    build(rson);
    MIN[rt] = min(MIN[rt<<1], MIN[rt<<1|1]);
}
void update(int p,  int l, int r, int rt)
{
    if(l == r) {
        MIN[rt].cnt++;
        return ;
    }
    int m = (l+r)>>1;
    if(p <= m) update(p,  lson);
    else update(p,  rson);
    MIN[rt] = min(MIN[rt<<1], MIN[rt<<1|1]);
}
int main()
{
    int q, x;
    scanf("%d%d", &q, &x);
    for(int i = 1; i <= x; ++i) num[i] = 0;
    build(1, x, 1);
    while(q--) {
        int temp;
        scanf("%d", &temp);
        update(temp%x+1, 1, x, 1);
        printf("%d\n", (MIN[1].cnt)*x+MIN[1].x-1);
    }
    return 0;
}

E. Obtain a Permutation

题意: 给你一个 n * m 的矩阵,你执行两种操作: ① 把矩阵中任意一个元素改为任意一个数 ② 把矩阵中任意一列整体往上挪一个单元格。
要求所有数符合 a[i][j] = (i - 1)*m+j。求最小操作次数。
思路:我们发现每一列的操作是独立的,所以就是求每一列变成要求的最小操作次数和。现在问题变成了如何求其中一列的最小操作次数,我们可以假设一列中其中一个元素是作为一列的第一个。这样就有n种情况,如果暴力的话,就是O(nnm)的时间复杂度,显然会爆。这时我们想一个数值在1到n*m的范围内有且仅有一个对应的位置。那么我们就可以通过上面的公式计算出对应的行号(前提是在数据范围内,且列不变)。我们先假设每个数据都是不对的,然后进行计算把对的情况减掉,最后求出那一个作为开头才是最小值。然后累加即可。
#include <bits/stdc++.h>
#define debug(x) cout <<#x<<" = "<<x<<endl
#define gg cout <<"---------------QAQ---------------"<<endl
#define fi first
#define se second
#define pb push_back
#define SZ(x) ((int)x.size())
#define ll long long
#define L(i,u) for (register int i=head[u]; i; i=nxt[i])
#define rep(i,a,b) for (register int i=(a); i<=(b); i++)
#define per(i,a,b) for (register int i=(a); i>=(b); i--)
#define inf 0x3f3f3f3f
#define lson l, m, rt<<1
#define rson m+1, r, rt<<1|1
using namespace std;
typedef unsigned int ui;
typedef pair<int,int> pii;
typedef vector<int> Vi;
template<class T> inline void read(T &x){
	x=0; char c=getchar(); int f=1;
	while (!isdigit(c)) {if (c=='-') f=-1; c=getchar();}
	while (isdigit(c)) {x=x*10+c-'0'; c=getchar();} x*=f;
}
const int N = 4066666;
void FAST(){ios::sync_with_stdio(false);cin.tie(0);}
 
int n, m;
int main()
{
    scanf("%d%d", &n, &m);
    vector<vector<int> > a(n+1, vector<int>(m+1));
    for(int i = 0; i < n; ++i) {
		for(int j = 0; j < m; ++j)
		{
			scanf("%d", &a[i][j]); a[i][j]--;
		}
	}
	int ans = 0;
	for(int j = 0;j < m; ++j) {
		vector<int> s(n+1);
		for(int i = 0; i < n; ++i) s[i] = i+n;
		for(int i = 0; i < n; ++i) {
			if(a[i][j]>=n*m||a[i][j]%m != j) continue;
			int temp = (i-a[i][j]/m)+n; temp %= n;
			s[temp]--;
		}
		ans += *min_element(s.begin(), s.begin()+n);
	}
	printf("%d\n", ans);
    return 0;
}
``
###### F看下面的博客吧,菜鸡的我不会。。。
###### 分享一个大佬写完的题解:https://www.cnblogs.com/StarRoadTang/p/12230408.html
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值