CF 1538 G. Gift Set (贪心+思维)

简介: 【6月更文挑战第14天】

链接

题意:

Polycarp有x个红糖和y个蓝糖,现在他想用这些糖果做一些礼品盒(gift set),但规定每个礼品盒里必须有a个红糖、b个蓝糖或b个红糖、a个蓝糖。现在求他最多能做成多少个礼品盒。

分析:

首先我们会发现这个题有很多种方法:二分($O(log(n))$),模拟($O(1)$),模拟退火等,

二分:

既然他是最多能做多少,那么我们可以发现,答案满足单调性,那么我们直接二分答案就好了。
首先我们找到那个用的糖果更少,假设a的更少。那么我们枚举的答案,一定满足:$x-aans>=0;y-aans>=0;$这是肯定的,因为如果用的少的都不满足跟不用提多的了,然后我们看如果$a=b$那么他一定是满足条件的,否则就是$a=ans$这样就是满足条件的,否则不满足。为什么那?其实就是用剩下的空变化一下成b,由a变成b需要加上$b-a$所以我们看有多少可以转化成b,如果比ans大或者相等那么这个ans是可以的,否则就不可以。

void solve(){
   
    scanf("%lld%lld%lld%lld", &n, &m, &a, &b);
    if(a>b) swap(a,b);
    ll l=0,r=1e9+7;
    while(l<r){
   
        ll mid=(l+r)/2;
        ll x=n,y=m;
        x-=a*mid;
        y-=a*mid;
        bool flag=(x>=0&&y>=0);
        if(b>a){
   ///防止出现a=b导致除以负数
            if(x/(b-a)+y/(b-a)<mid) flag=0;
        }
        if(flag) l=mid+1;
        else r=mid;
    }
    cout<<l-1<<endl;
}

模拟($O(1)$)

我们让n<m,a<b
我们分析出来他其实就是那么 一些(a+b,a+b)这样的二元组,和一些(a,b)这样的二元组。
我们发现我们选一个二元组(a,b)会让(n,m)之间的差缩减(b-a).所以我们可以先选$\frac{m-n}{b-a}$个(a,b)剩下的可以全选(a+b,a+b);

如果我们最后选完(a+b,a+b),还剩的够再买一个(a,b)或者(b,a)这样的二元组,那么我们就需要在做一次贡献。

需要特判一下,a=b因为不能除以0.答案是($\frac{n}{a}$)

void solve()
{
   
    scanf("%lld%lld%lld%lld", &n, &m, &a, &b);    
    ///O(1)
    if(n>m) swap(n,m);
    if(a>b) swap(a,b);
    if(n<a||m<b) {
   
        puts("0");
        return ;
    }
    ll ca=m-n,cb=b-a;
    if(cb==0){
   
        printf("%lld\n",n/a);
        return;
    }
    ll num=min(ca/cb,min(n/a,m/b));
    n-=num*a;m-=num*b;
    ll ans=num+min(n,m)/(a+b)*2;
    if(n>=a&&m>=b) n-=a,m-=b,num++;
    printf("%lld\n",max(ans,num+min(n,m)/(a+b)*2));
}

链接

题意:

给出二维平面上的 $n$ 个点,任意选择出三个点可以构成一个三角形,现在问满足下面条件的三角形的个数:

  • 三角形面积为整数
  • 三角形包含的(不包括边界)整数点为奇数
  • 其中所有坐标点的 $x$ 和 $y$ 都是偶数

    分析:

    首先看下需要用到的定理之类的东西:
  1. 已知三角形三个点,求三角形面积
    $S=\frac{x_1(y_2-y_3)+x_2(y_3-y_1)+x_3(y_1-y_2)}{2}$
  2. 皮克定理
    用于求多边形面积。$S=a+\frac{b}{2}-1$其中a是多边形内部的整点数,b是多边形边界点数。S是多边形面积。边界上的点数为$gcd(x_1-x_2,y_1-y_2)+1$
// Problem: F1. Gregor and the Odd Cows (Easy)
// Contest: Codeforces - Codeforces Round #736 (Div. 2)
// URL: https://codeforces.com/contest/1549/problem/F1
// Memory Limit: 256 MB
// Time Limit: 6000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
typedef unsigned long long ull;

#define x first
#define y second
#define sf scanf
#define pf printf
#define PI acos(-1)
#define inf 0x3f3f3f3f
#define lowbit(x) ((-x)&x)
#define mem(a,x) memset(a,x,sizeof(a))
#define rep(i,n) for(int i=0;i<(n);++i)
#define repi(i,a,b) for(int i=int(a);i<=(b);++i)
#define repr(i,b,a) for(int i=int(b);i>=(a);--i)
#define debug(x) cout << #x << ": " << x << endl;

const int MOD = 998244353;
const int mod = 1e9 + 7;
const int maxn = 2e5 + 10;    
const int dx[] = {
   0, 1, -1, 0, 0};
const int dy[] = {
   0, 0, 0, 1, -1};
const int dz[] = {
   1, -1, 0, 0, 0, 0 };
int day[] = {
   0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};

ll dp[2][2];

ll C(ll n,ll m){
   
    if(m==1) return n;
    else if(m==2)return n*(n-1)/2;
    else if(m==3) return (n-1)*(n-2)*n/6;
}

void solve()
{
   
    ll n;    
    scanf("%lld\n",&n);
    for(int i=1;i<=n;i++){
   
        int x, y;
        scanf("%d%d",&x,&y);
        dp[x%4/2][y%4/2]++;
    }
    ll ans=0;
    for(ll i=0;i<4;i++){
   
        for(ll j=i;j<4;j++){
   
            for(ll k=j;k<4;k++){
   
                ll x1=i/2,y1=i%2;
                ll x2=j/2,y2=j%2;
                ll x3=k/2,y3=k%2;
                ll sum=0;
                sum+=(x1==x2&&y1==y2);
                sum+=(x3==x2&&y3==y2);
                sum+=(x1==x3&&y1==y3);
                if(sum==0||sum==2) continue;
                if(i==j&&i==k) ans+=C(dp[x1][y1],3);
                else if(i==j) ans+=C(dp[x1][y1],2)*dp[x3][y3];
                else if(k==j) ans+=C(dp[x2][y2],2)*dp[x1][y1];
                else if(i==k) ans+=C(dp[x1][y1],2)*dp[x2][y2];
                else ans+=dp[x1][y1]*dp[x2][y2]*dp[x3][y3];
            }
        }
    }
    cout<<ans<<endl;
}

int main()
{
   
    ll t = 1;
    //scanf("%lld",&t);
    while(t--)
    {
   
        solve();
    }
    return 0;
}
目录
相关文章
|
2月前
|
存储 缓存 JavaScript
Set和Map有什么区别?
Set和Map有什么区别?
236 1
|
6月前
|
编译器 C++ 容器
【c++丨STL】基于红黑树模拟实现set和map(附源码)
本文基于红黑树的实现,模拟了STL中的`set`和`map`容器。通过封装同一棵红黑树并进行适配修改,实现了两种容器的功能。主要步骤包括:1) 修改红黑树节点结构以支持不同数据类型;2) 使用仿函数适配键值比较逻辑;3) 实现双向迭代器支持遍历操作;4) 封装`insert`、`find`等接口,并为`map`实现`operator[]`。最终,通过测试代码验证了功能的正确性。此实现减少了代码冗余,展示了模板与仿函数的强大灵活性。
167 2
|
3月前
|
存储 JavaScript 前端开发
for...of循环在遍历Set和Map时的注意事项有哪些?
for...of循环在遍历Set和Map时的注意事项有哪些?
97 0
|
3月前
|
存储 C++ 容器
unordered_set、unordered_multiset、unordered_map、unordered_multimap的介绍及使用
unordered_set是不按特定顺序存储键值的关联式容器,其允许通过键值快速的索引到对应的元素。在unordered_set中,元素的值同时也是唯一地标识它的key。在内部,unordered_set中的元素没有按照任何特定的顺序排序,为了能在常数范围内找到指定的key,unordered_set将相同哈希值的键值放在相同的桶中。unordered_set容器通过key访问单个元素要比set快,但它通常在遍历元素子集的范围迭代方面效率较低。它的迭代器至少是前向迭代器。前向迭代器的特性。
175 0
|
3月前
|
编译器 C++ 容器
用一棵红黑树同时封装出map和set
再完成上面的代码后,我们的底层代码已经完成了,这时候已经是一个底层STL的红黑树了,已经已符合库里面的要求了,这时候我们是需要给他穿上对应的“衣服”,比如穿上set的“衣服”,那么这个穿上set的“衣服”,那么他就符合库里面set的要求了,同样map一样,这时候我们就需要实现set与map了。因此,上层容器map需要向底层红黑树提供一个仿函数,用于获取T当中的键值Key,这样一来,当底层红黑树当中需要比较两个结点的键值时,就可以通过这个仿函数来获取T当中的键值了。我们就可以使用仿函数了。
42 0
|
3月前
|
存储 编译器 容器
set、map、multiset、multimap的介绍及使用以及区别,注意事项
set是按照一定次序存储元素的容器,使用set的迭代器遍历set中的元素,可以得到有序序列。set当中存储元素的value都是唯一的,不可以重复,因此可以使用set进行去重。set默认是升序的,但是其内部默认不是按照大于比较,而是按照小于比较。set中的元素不能被修改,因为set在底层是用二叉搜索树来实现的,若是对二叉搜索树当中某个结点的值进行了修改,那么这棵树将不再是二叉搜索树。
189 0
|
7月前
|
编译器 容器
哈希表模拟封装unordered_map和unordered_set
哈希表模拟封装unordered_map和unordered_set
|
7月前
|
编译器 测试技术 计算机视觉
红黑树模拟封装map和set
红黑树模拟封装map和set