2020 wannafly camp 补题 day1

题目链接:https://codeforces.com/group/6QKpZkKhsL/contest/265753

最简单的一个题应该是B

B. 密码学

这个应该就是倒着推,题目给了你加密的顺序,所以我们逆推这个就可以得到每一次加密前的字符串。

 

1H. 最大公约数

题目大意就是给你一个范围1~n 满足gcd(k,y) 是独一无二的,意思是除了k之外,1~n中没有gcd(i,y)==gcd(k,y)

这个题目首先要知道gcd(k,y)==k,因为如果等于x,且x<k,那么因为x属于1~n,所以gcd(x,y)==x

这样就不满足题目要求了。

所以y一定是k的倍数,因为在这n个数中,可能有很多数都是k的整数倍,那么这个y要满足要求,则必须是

gcd(m*k,y)!=k,所以如果有数是k的素数倍,那么y也一定是这个素数的倍数。

这个会爆long long 。

 

F. 乘法

这个算法是二分,二分这个第k大,然后check。

这个check有点难写,因为有正有负需要分开写。

最后对我来说比较坑的地方是因为取过膜,所以不可以直接除以2,需要乘以2的逆元

#include<iostream>
#include<cstdio>
#include<cstring>
#include<bits/stdc++.h>
#define inf64 0x3f3f3f3f3f3f3f3f
using namespace std;
const int maxn=1e5+10;
typedef long long ll;
ll a[maxn],b[maxn];
ll a1[maxn],a2[maxn],b1[maxn],b2[maxn];
ll tota1=0,tota2=0,totb1=0,totb2=0,zera=0,zerb=0;
ll n,m,k;
bool check(ll x){
    ll sum=0;
    if(x<=0){
        sum+=tota1*totb1+tota2*totb2+zera*m+zerb*n-zera*zerb;
//        printf("sum=%lld\n",sum);
        if(x==0) return sum>=k;
        if(sum>=k) return true;
        x=-x;
        for(int i=1;i<=tota1&&totb2;i++){
            ll t=upper_bound(b2+1,b2+1+totb2,x/a1[i])-b2;
            if(b2[t]>x/a1[i]||t>totb2) t--;
            sum+=t;
//            printf("aa i=%d sum=%lld t=%d %d\n",i,sum,t,totb2);
        }
        for(int i=1;i<=tota2&&totb1;i++){
            ll t=upper_bound(b1+1,b1+1+totb1,x/a2[i])-b1;
//            printf("t=%d\n",t);
            if(b1[t]>x/a2[i]||t>totb1) t--;
            sum+=t;
//            printf("i=%d sum=%lld t=%d\n",i,sum,t);
            
        }
//        printf("x=%lld sum=%lld\n",x,sum);
        return sum>=k;
    }
    for(int i=1;i<=tota1&&totb1;i++){
        ll val=x/a1[i];
        if(x%a1[i]) val++;
        int t=lower_bound(b1+1,b1+1+totb1,val)-b1;
        sum+=totb1-t+1;
    }
    for(int i=1;i<=tota2&&totb2;i++){
        ll val=x/a2[i];
        if(x%a2[i]) val++;
        int t=lower_bound(b2+1,b2+1+totb2,val)-b2;
        sum+=totb2-t+1;
    }
    return sum>=k;
}
int main(){
    scanf("%lld%lld%lld",&n,&m,&k);
    for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
    for(int i=1;i<=m;i++) scanf("%lld",&b[i]);
    for(int i=1;i<=n;i++){
        if(a[i]<0) a1[++tota1]=-a[i];
        else if(a[i]>0) a2[++tota2]=a[i];
        else zera++;
    }
    for(int i=1;i<=m;i++){
        if(b[i]<0) b1[++totb1]=-b[i];
        else if(b[i]>0) b2[++totb2]=b[i];
        else zerb++;
    }
    sort(a1+1,a1+1+tota1);
    sort(a2+1,a2+1+tota2);
    sort(b1+1,b1+1+totb1);
    sort(b2+1,b2+1+totb2);
//    printf("%d %d %d %d\n",tota1,tota2,totb1,totb2);
    ll l=-inf64,r=inf64,ans=0;
    while(l<=r){
        ll mid=(l+r)>>1;
        if(check(mid)) ans=mid,l=mid+1;
        else r=mid-1;
    }
    printf("%lld\n",ans);
    return 0;
}
/*
1 2 2
2
-3 -3
 
*/
F

猜你喜欢

转载自www.cnblogs.com/EchoZQN/p/12194433.html