codeforces数学1700[CodeForces 1336B[分类讨论+二分]CodeForces - 1301C[组合计数的减法原理]]

CodeForces 1336B Xenia and Colorful Gems


题目大意:给你 n r n_r nr x i x_i xi n g n_g ng y i y_i yi n b n_b nb z i z_i zi,从中挑出一个 x j , y j , z j x_j,y_j,z_j xjyjzj使得 ( x − y ) 2 + ( y − z ) 2 + ( z − x ) 2 (x-y)^2+(y-z)^2+(z-x)^2 (xy)2+(yz)2+(zx)2最小


解题思路:qwq(自己没想出来)感觉思路还是挺妙的:
1.我们先给 x , y , z x,y,z x,y,z自己定一个大小顺序,无非就6种情况:
(1) x < = y < = z x<=y<=z x<=y<=z
(2) z < = y < = x z<=y<=x z<=y<=x
(3) z < = x < = y z<=x<=y z<=x<=y
(4) y < = x < = z y<=x<=z y<=x<=z
(5) y < = z < = x y<=z<=x y<=z<=x
(6) x < = z < = y x<=z<=y x<=z<=y

2.对于每一种情况我们可以枚举中间的比如说情况1:我们枚举 y y y的所有数去 x x x集合中找第一个小于等于 y y y的数,去 z z z集合找第一个大于等于 y y y的数。如果找不到就返回 I N F INF INF


#pragma GCC optimize(2)
#include <bits/stdc++.h>
#define ll long long

using namespace std;
const int mod=1e9+7;
const int manx=1e5+5;
ll t,a1,b1,c1;
ll a[manx],b[manx],c[manx];
char s[manx];
ll checks(ll a[],ll a1,ll b[],ll b1,ll c[],ll c1)
{
 
    ll add=2e18,x,y,z;
    for(int i=1; i<=a1; i++)
    {
        x=a[i];
        ll k=lower_bound(b+1,b+1+b1,x)-b;
        if(k>=1&&k<=b1&&b[k]>=x) y=b[k];
        else  continue;
        ll l=1,r=c1;
        while(l<r)
        {
            int mid=(l+r+1)>>1;
            if(c[mid]<=x) l=mid;
            else r=mid-1;
        }
        if(c[l]<=x)  z=c[l];
        else continue;
        ll d=(y-z)*(y-z)+(x-y)*(x-y)+(x-z)*(x-z);
        if(d<add) add=d;
    }
    return add;
}
int main()
{
	ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
     t;
	cin>>t;
    while(t--)
    {
        cin>>a1;cin>>b1;cin>>c1;
        for(int i=1;i<=a1;i++) cin>>a[i];
        for(int i=1;i<=b1;i++) cin>>b[i];
        for(int i=1;i<=c1;i++) cin>>c[i];
        sort(a+1,a+1+a1);
        sort(b+1,b+1+b1);
        sort(c+1,c+1+c1);
        ll ans=2e18;
        ans=min(ans,checks(a,a1,b,b1,c,c1));ans=min(ans,checks(a,a1,c,c1,b,b1));
        ans=min(ans,checks(b,b1,a,a1,c,c1));ans=min(ans,checks(b,b1,c,c1,a,a1));
        ans=min(ans,checks(c,c1,b,b1,a,a1));ans=min(ans,checks(c,c1,a,a1,b,b1));
        cout<<ans<<endl;
    }
}


C - Ayoub’s function CodeForces - 1301C


题目大意:给你一个长度为 n n n的01串,其中这个01串中有 m m m个1。在这里我们定义了一个好子串就是这个子串内部必须包含一个1(不全为0)(子串是连续的),定义 s u m sum sum为好子串的个数问怎么排列01使得 s u m sum sum最大


解题思路:1.如果我们全部为1,那么 s u m = n ∗ ( n + 1 ) 2 sum={n*(n+1)\over2} sum=2n(n+1)假设我们有连续 l l l个0,那么没有贡献的子串个数就是 l ∗ ( l + 1 ) 2 {l*(l+1)\over2} 2l(l+1)
2.现在我们有 m m m个1那么就有 n − m n-m nm个0,那么就有 m + 1 m+1 m+1个空隙去插入0,那么就是将 n − m n-m nm个0分成 m + 1 m+1 m+1组使得每一组的 l ∗ ( l + 1 ) 2 {l*(l+1)\over2} 2l(l+1)最小,那么很显然就是平分

在这里插入图片描述

#include <iostream>
#include <cstdio>
#include <stack>
#include <vector>
#include <map>
#include <cstring>
#include <deque>
#include <cmath>
#include <iomanip>
#include <queue>
#include <algorithm>
#include <set>
#define mid ((l + r) >> 1) 
#define Lson rt << 1, l , mid
#define Rson rt << 1|1, mid + 1, r
#define ms(a,al) memset(a,al,sizeof(a))
#define sfx(x) scanf("%lf",&x)
#define sfxy(x,y) scanf("%lf%lf",&x,&y)
#define sdx(x) scanf("%d",&x)
#define sdxy(x,y) scanf("%d%d",&x,&y)
#define pfx(x) printf("%.0f\n",x)
#define pfxy(x,y) printf("%.6f %.6f\n",x,y)
#define pdx(x) printf("%d\n",x)
#define pdxy(x,y) printf("%d %d\n",x,y)
#define _for(i,a,b) for( int i = (a); i < (b); ++i)
#define _rep(i,a,b) for( int i = (a); i <= (b); ++i)
#define for_(i,a,b) for( int i = (a); i >= (b); -- i)
#define rep_(i,a,b) for( int i = (a); i > (b); -- i)
#define IOS std::ios::sync_with_stdio(0); cin.tie(0); cout.tie(0)
#define INF 0x3f3f3f3f-
#define hash Hash
#define endl '\n'
#define next Next
#define f first
#define s second
#define lowbit(x) (x & (-x))
using namespace std;
const int N = 2e5 + 10, eps = 1e-10;

typedef long long LL;
typedef unsigned long long ULL;
typedef pair<LL,LL> PII;
LL n, m;
int a[N << 1];
int main()
{
    IOS;
    int T;
    cin >> T;
    
    while(T --)
    {
        cin >> n >> m;
        LL ans = n * (n + 1) / 2;
        LL z = n - m;
        LL k = z / (m + 1);
        ans -= (m + 1) * k * (k + 1) / 2;
        ans -= (z % (m + 1)) * (k + 1);
        cout << ans << endl;
    }
    
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值