Daily Practice 3rd: Codeforces Round #757 (Div. 2)

VP*3  :P

rating:800--1000--1500;

A. Divan and a Store(greedy,sorting)

给出可选择的巧克力价格区间和可支配的钱数,问最多可以买多少巧克力。

 思路:排序,遍历可满足条件的情况,贪心求解即可。

AC Code:

#include <bits/stdc++.h>

template <typename T>
inline void read(T &x) {
	x = 0;
	int f = 1;
	char ch = getchar();
	while (!isdigit(ch)) {
		if (ch == '-')
			f = -1;
		ch = getchar();
	}
	while (isdigit(ch)) {
		x = x * 10 + ch - '0', ch = getchar();
	}
	x *= f;
}

template <typename T>
void write(T x) {
	if (x < 0)
		putchar('-'), x = -x;
	if (x > 9)
		print(x / 10);
	putchar(x % 10 + '0');
}

#define INF 0x3f3f3f3f
typedef long long ll;
const double PI = acos(-1);
const double eps = 1e-6;
const int mod = 1e9 + 7;
const int N = 200 + 5;
int t,n,l,r,k,a[N];

int main() {
//	freopen("test.in","r",stdin);
//  freopen("output.in", "w", stdout);
	std::ios::sync_with_stdio(false);
	std::cin.tie(0);
    std::cin>>t;
    while(t--){
        std::cin>>n>>l>>r>>k;
        for(int i=1;i<=n;i++){
            std::cin>>a[i];
        }
        std::sort(a+1,a+1+n);
        ll cnt=0,sum=0;
        for(int i=1;i<=n;i++){
            if(a[i]>=l&&sum+a[i]<=k&&a[i]<=r)
                cnt++,sum+=a[i];;
        }
        std::cout<<cnt<<'\n';
    }
	return 0;
}

B. Divan and a New Project(greedy,queue)

给出n栋楼每栋需要去的次数,问将每栋楼建在什么位置可使完成每栋楼去的次数后,路程最短。

思路: 贪心思想,将去的次数多的楼建在距离起点最近的地方,为了简化问题,可以将起点放在坐标原点,按照次数排序后一左一右放置在起点左右两侧。具体实现时,我是用的结构体+优先队列,因为输出结果时要按照原来的位置输出。

AC Code:

#include <bits/stdc++.h>

template <typename T>
inline void read(T &x) {
	x = 0;
	int f = 1;
	char ch = getchar();
	while (!isdigit(ch)) {
		if (ch == '-')
			f = -1;
		ch = getchar();
	}
	while (isdigit(ch)) {
		x = x * 10 + ch - '0', ch = getchar();
	}
	x *= f;
}

template <typename T>
void write(T x) {
	if (x < 0)
		putchar('-'), x = -x;
	if (x > 9)
		print(x / 10);
	putchar(x % 10 + '0');
}

#define INF 0x3f3f3f3f
typedef long long ll;
const double PI = acos(-1);
const double eps = 1e-6;
const int mod = 1e9 + 7;
const int N = 2e5 + 5;
ll t,n;

struct node{
    ll tim,id,pos;
    bool operator <(const node&a) const{
        return id>a.id;
    }
}e[N];

bool cmp(node a,node b){
    if(a.tim>b.tim) return true;
    else return false;
}

int main() {
//	freopen("test.in","r",stdin);
//  freopen("output.in", "w", stdout);
	std::ios::sync_with_stdio(false);
	std::cin.tie(0);
    std::cin>>t;
    while(t--){
        std::cin>>n;
        for(ll i=1;i<=n;i++){
            e[i].id=i;
            std::cin>>e[i].tim;
        }
        std::sort(e+1,e+1+n,cmp);
        for(ll i=1;i<=n;i++){
        }
        ll tt=0,oo=0;
        for(ll i=1;i<=n;i++){
            if(i%2==1){
                e[i].pos=++tt;
            }
        }
        for(ll i=1;i<=n;i++){
            if(i%2==0){
                e[i].pos=++oo;
                e[i].pos=-oo;
            }
        }
        std::priority_queue<node>pq;
        ll ans=0;
        for(ll i=1;i<=n;i++){
            ans+=abs(e[i].pos)*2*e[i].tim;
            pq.push(e[i]);
        }
        std::cout<<ans<<'\n';
        std::cout<<0<<' ';
        while(!pq.empty()){
            node now=pq.top();
            std::cout<<now.pos<<' ';
            pq.pop();
        }
        std::cout<<'\n';
    }
	return 0;
}

os:哦,记得开long long,,,

C. Divan and bitwise operations(bitmasks,combinatorics)

 给出m个区间或以及左右区间端点值,构造一个满足该条件且有n个元素的数组,计算该数组所有子序列异或的和。

思路:首先根据或运算,所有给出区间或运算的或和就是全部原数组的或和,可以反映出原数组所有数某一位上是否有1的情况。然后,我们其实是无法确定n个数该位有多少个1,我们只能确定n个数该位是否有1,我们先假设n个数的第i位有q个1,那么就有n-q个0。当该位对于最后的答案有贡献时,则要在q个1中选择奇数个(由异或可知),那么就是C(1,q)+C(3,q)+...,即选择所有奇数的情况和,根据二项式定理,选择奇数=选择偶数=2^{n-1},那就是2^{q-1};可以计算每一位对于答案的贡献都是2^{q-1}*2^{n-q}*2^{i},而对于该位没有1的位,对于答案没有贡献不必计算。这样总结下来,可以直接把所有区间或再进行或运算,得到res,答案就是2^{q-1}*2^{n-q}*res,这个2^{q-1}*2^{n-q}其实是异或非0的方案数,乘以每一位的位权res。然后我们发现这个式子可以化简,得到答案是res*2^{n-1}!也就是说,对于所有数的某一位,有几个数的该位是1并不重要!

AC Code:

#include <bits/stdc++.h>

template <typename T>
inline void read(T &x) {
	x = 0;
	int f = 1;
	char ch = getchar();
	while (!isdigit(ch)) {
		if (ch == '-')
			f = -1;
		ch = getchar();
	}
	while (isdigit(ch)) {
		x = x * 10 + ch - '0', ch = getchar();
	}
	x *= f;
}

template <typename T>
void write(T x) {
	if (x < 0)
		putchar('-'), x = -x;
	if (x > 9)
		print(x / 10);
	putchar(x % 10 + '0');
}

#define INF 0x3f3f3f3f
typedef long long ll;
const double PI = acos(-1);
const double eps = 1e-6;
const int mod = 1e9 + 7;
const int N = 2e5 + 5;
ll t,n,m,l,r,k;

ll pmod(ll a,ll b){
    ll res=1;
    while(b){
        if(b%2) res=res*a%mod;
        b>>=1;
        a=a*a%mod;
    }
    return res;
}

int main() {
//	freopen("test.in","r",stdin);
//  freopen("output.in", "w", stdout);
	std::ios::sync_with_stdio(false);
	std::cin.tie(0);
    std::cin>>t;
    while(t--){
        std::cin>>n>>m;
        ll ans=0;
        for(ll i=1;i<=m;i++){
            std::cin>>l>>r>>k;
            ans|=k;
        }
        ans%=mod;
        std::cout<<ans%mod*pmod(2,n-1)%mod%mod<<'\n';
    }
	return 0;
}

太菜了C题搞了将近一晚上才刚刚明白,,,

若有错误请指教orzorz

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值