牛客网多校第五场

A:gpa

 分数规划裸题了吧,然后二分次数过多的话会超时

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
 
using namespace std;
 
const int MAX=1e5+5;
int n,k;
double s[MAX],c[MAX];
double tmp[MAX];
 
int check(double x){
    int i;
    double ans=0;
    for(i=0;i<n;i++)
        tmp[i]=s[i]*c[i]-x*s[i];
    sort(tmp,tmp+n);
    for(i=n-1;i>=k;i--)
        ans+=tmp[i];
    if(ans>0) return 1;
    return 0;
}
 
double bsearch(double left,double right){
    int i;
    double mid;
     
    for(i=0;i<60;i++){
        mid=(left+right)/2;
        if(check(mid))
            left=mid;
        else
            right=mid;
    }
    return mid;
}
 
int main(){
    int i;
     
    scanf("%d%d",&n,&k);
    for(i=0;i<n;i++)
        scanf("%lf",&s[i]);
    for(i=0;i<n;i++)
        scanf("%lf",&c[i]);
    double ans=bsearch(0,1e9);
    printf("%.7lf\n",ans);
     
    return 0;
}
View Code

B: div

 主要是结论比较难构造出来,当然如果oeis技巧足够强,这就是小事。推出结论就很简单了,java大数随便写写就好了

附结论证明

import java.math.BigInteger;
import java.util.Scanner;
 
public class Main {
    public static void main(String[] args)
    {
        Scanner cin = new Scanner(System.in);
        BigInteger m=cin.nextBigInteger();
        BigInteger a1 =new BigInteger("0");
        BigInteger a2 =new BigInteger("2");
        BigInteger b1 =new BigInteger("0");
        BigInteger b2 =new BigInteger("6");
        BigInteger a3,b3;
        BigInteger k1 =new BigInteger("6");
        BigInteger k2 =new BigInteger("14");
        while(a2.compareTo(m)<=0)
        {
            a3=a2.multiply(k1).subtract(a1);
            a1=a2;
            a2=a3;     
        }
         
        while(b2.compareTo(m)<=0)
        {
            b3=b2.multiply(k2).subtract(b1);
            b1=b2;
            b2=b3;     
        }
         
        System.out.println(a2.min(b2));
    }
}
View Code

D: inv

E:room

 二分图最大权值匹配,将旧安排和新安排两两之间建边,容量为1,权值为这两个房间相同人的数量。因为凡是前后不在同一个宿舍的人可以只通过一次就交换到新宿舍,所以只要不交换的人尽量多即可

#include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>
#include <cmath>
#include <vector>
#include <stack>
#include <set>
using namespace std;
 
const int INF=0x3f3f3f3f;
const int MAX=1e3+5;
const int ext=200;
struct node{
    int v,f,cost,next;
}edge[MAX*MAX];
int no,s,t;
int head[MAX],dis[MAX],vis[MAX],pre[MAX],rec[MAX]; //pre记录前驱 rec记录边在edge中编号
queue<int> q;
 
void init(void){
    no=0;
    memset(head,-1,sizeof head);
}
 
void addedge(int u,int v,int f,int cost){
    edge[no].v=v; edge[no].f=f; edge[no].cost=cost;
    edge[no].next=head[u]; head[u]=no++;
    edge[no].v=u; edge[no].f=0; edge[no].cost=-cost;
    edge[no].next=head[v]; head[v]=no++;
}
 
int spfa(int s,int t){
    int k,tp;
     
    memset(dis,0x3f,sizeof(dis));
    memset(vis,0,sizeof(vis));
    while(!q.empty())
        q.pop();
    q.push(s);
    dis[s]=0;
    vis[s]=1;
    while(!q.empty()){
        tp=q.front();
        q.pop();
        vis[tp]=0;
        for(k=head[tp];k!=-1;k=edge[k].next)
            if(dis[edge[k].v]>dis[tp]+edge[k].cost&&edge[k].f){
                dis[edge[k].v]=dis[tp]+edge[k].cost;
                pre[edge[k].v]=tp;
                rec[edge[k].v]=k;
                if(vis[edge[k].v]==0){
                    vis[edge[k].v]=1;
                    q.push(edge[k].v);
                }
            }
    }
    if(dis[t]==INF)
        return 0;
    return 1;
}
 
pair<int, int> Mcmf(int s,int t){
    int minflow,k,mincost=0,maxflow=0;
    while(spfa(s,t)){
        k=t;
        minflow=INF;
        while(k!=s){
            minflow=min(minflow,edge[rec[k]].f);
            k=pre[k];
        }
        k=t;
        maxflow+=minflow;
        while(k!=s){
            mincost+=minflow*edge[rec[k]].cost;
            edge[rec[k]].f-=minflow;
            edge[rec[k]^1].f+=minflow;
            k=pre[k];
        }
    }
    return make_pair(maxflow,mincost);
}
 
int n;
int x[MAX][10],y[MAX][10];
 
int main(){
    int i,j,k,p;
     
    init();
    scanf("%d",&n);
    for(i=1;i<=n;i++)
        for(j=0;j<4;j++)
            scanf("%d",&x[i][j]);
    for(i=1;i<=n;i++){
        for(j=0;j<4;j++)
            scanf("%d",&y[i][j]);
        for(j=1;j<=n;j++){
            int cnt=0;
            for(k=0;k<4;k++)
                for(p=0;p<4;p++)
                    if(y[i][k]==x[j][p])
                        cnt++;
        addedge(j,i+ext,1,4-cnt);
        }
    }
    int s=0,t=200+ext;
    for(i=1;i<=n;i++){
        addedge(s,i,1,0);
        addedge(i+ext,t,1,0);
    }  
    pair<int,int> ans=Mcmf(s,t);
    printf("%d\n",ans.second);
     
    return 0;
}
View Code

F: take

G:max

 取[1,n/c]中的最大两个就行,然后特别讨论一下n/c=1情况

#include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>
#include <cmath>
#include <vector>
#include <iostream>
#include <stack>
#include <set>
#include <map>
#define LSON l,m,x<<1
#define RSON m+1,r,x<<1|1
using namespace std;
 
long long c,n;
 
int main(){
     
    scanf("%lld%lld",&c,&n);
    long long x=n/c;
    if(x<1){
        puts("-1");
        return 0;
    }
    if(x==1){
        printf("%lld\n",c*c);
        return 0;
    }
    long long ans=x*(x-1);
    printf("%lld\n",ans*c*c);
     
    return 0;
}
View Code

H:subseq

I:vcd

J:plan

 待填

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
 
using namespace std;
 
typedef long long LL;
 
long long n,p1,p2;
long long ans;
 
int main(){
    scanf("%lld%lld%lld",&n,&p1,&p2);
    LL tmp1,tmp2;
    tmp1=(n/2)*p1;
    tmp2=(n/3)*p2;
    if(n%2==1){
        LL tmp;
        tmp=min(p1,p2);
        if(tmp1) tmp=min(tmp,-p1+p2);
        tmp1+=tmp;
    }
    if(n%3==1){
        LL tmp;
        tmp=min(p1,p2);
        if(tmp2) tmp=min(tmp,-p2+p1+p1);
        tmp2+=tmp;
    }
    else if(n%3==2){
        LL tmp;
        tmp=min(p1,p2);
        tmp2+=tmp;
    }
    printf("%lld",min(tmp1,tmp2));
    return 0;
}
View Code

猜你喜欢

转载自www.cnblogs.com/Hetui/p/9424516.html