hihoCoder-[Offer收割]编程练习赛100

A:题目1 : 鱼的战斗

时间限制:10000ms
单点时限:1000ms
内存限制:256MB
描述
如下所示,在一条直线上,N条鱼往左游,N条鱼往右游。如果两条鱼相遇,大鱼就会吃掉小鱼。
AN AN-1 … A3 A2 A1 -> <- B1 B2 B3 … BN-1 BN
给定2N条鱼的大小,(保证没有2条鱼大小相同),请你计算最后会剩下多少条鱼。
输入
第一行包含一个整数N。
第二行包含N个整数A1, A2, … AN。
第三行包含N个整数B1, B2, … BN。
1 <= N <= 100
1 <= Ai, Bi <= 1000
输出
一个整数代表答案

样例输入
3
2 7 3
4 5 6

样例输出
2

解释:直接模拟就好了。。。

#include <iostream>
using namespace std;
int n=0;
int a[1003]={0};
int b[1003]={0};
int main(){
    cin>>n;
    for(int i=1;i<=n;i++) cin>>a[i];
    for(int i=1;i<=n;i++) cin>>b[i];
    int i=1,j=1;
    while(i<=n&&j<=n){
        if(a[i]>b[j]) j++;
        else i++;
    }
    cout<<max(n-i,n-j)+1<<endl;
    return 0;
}

B:奇因子之和

时间限制:10000ms
单点时限:1000ms
内存限制:256MB
描述
H国有一个很特殊的数学信仰,他们认为只包含2、3、5和7这四个质因子的数是真数,否则就是假数。
例如2、6、20、98等都是真数,11、26、85等都是假数。
在H国的一次全国中学生数学竞赛上,给出了N个真数A1, A2, … AN。
请你计算每一个Ai的奇因子之和。
例如90的奇因子有1、3、5、9、15、45,和是78。
输入
第一行包含一个整数N。
以下N行每行包含一个整数Ai,保证Ai是真数。
对于80%的数据,2 <= Ai <= 1000000
对于100%的数据,1 <= N <= 10000 2 <= Ai <= 1000000000000000
输出
输出N行,每行一个整数代表对应的答案

样例输入
2
2
90

样例输出
1
78

解释: a i a_i ai = 2a * 3b * 5c * 7d,那我们把 a i a_i ai的2因子全都除掉,剩下的直接求和就好了, s u m i sum_i sumi = (30+31…+3b)(50+51…+5c)(70+71…+7c). sum = ∑ i = 1 n s u m i \sum_{i=1}^nsum_i i=1nsumi

#include <iostream>
#include<cstdio>
#define N 10003
using namespace std;
int n=0;
long long a[N]={0};
long long ok(long long x){
    while(x%2==0) x/=2;
    long long ret=1;
    for(int i=3;i<=7;i+=2){
        long long temp=1;
        long long sum=1;
        int num=0;
        while(x%i==0){
            num++;x/=i;
            temp*=i;
            sum+=temp;
        }
        ret=ret*sum;
    }
    return ret;
}
int main(){
    ios::sync_with_stdio(false);
    scanf("%d",&n);
    for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
    for(int i=1;i<=n;i++) printf("%lld\n",ok(a[i]));
    return 0;
}

C:选择奏折

时间限制:10000ms
单点时限:1000ms
内存限制:256MB
描述
H帝国幅员辽阔,每天都有茫茫多的奏折如雪片般从各地送到皇帝面前。不过当朝皇帝不太勤勉,他决定只披阅由军机大臣挑选上的奏折。
皇帝手下一共有M名军机大臣,他们每天挑选奏折的过程如下:
首先将当天收到的奏折编号1~N。
第一名军机大臣心里默念一个整数A1,然后从所有奏折中将编号是A1倍数的奏折挑选出来;
第二名军机大臣心里默念一个整数A2,然后从剩余奏折中将编号是A2倍数的奏折挑选出来;
……
第M名军机大臣心里默念一个整数AM,然后从剩余奏折中将编号是AM倍数的奏折挑选出来;
请你计算当天皇帝一共要披阅多少份奏折?
输入
第一行包含两个整数N和M,依次是奏折数目和军机大臣数目。
以下M行每行包含一个整数Ai。
对于50%的数据,1 <= N <= 10000000
对于100%的数据,1 <= N <= 1000000000000 1 <= M <= 10 1 <= Ai <= 100000
输出
一个整数代表答案

样例输入
10 2
3
5

样例输出
5

解释:很明显直接容斥就好了。实现的话直接枚举二进制位,每位代表一个 a i a_i ai.

include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
long long a[13]={0};
long long n=0,m=0;
long long ret=0;
long long gcd(long long a,long long b){
    if(b==0) return a;
    return gcd(b,a%b);
}
long long lcm(long long a,long long b){
    return a*b/gcd(a,b);
}
long long fun(int state){
    int num=0;
    int mark=0;
    long long sum=0;
    while(state){
        if(state&1){
            mark++;
            if(mark==1){
                sum=a[num];
            }else{
                sum=lcm(sum,a[num]);
            }
        }
        num++;state/=2;
    }
    sum=n/sum;
    if(mark%2==0) sum=-sum;
    return sum;
}
int main(){
    cin>>n>>m;
    for(int i=0;i<m;i++) cin>>a[i];
    for(int i=1;i<(1<<m);i++){
        ret+=fun(i);
    }
    cout<<ret<<endl;
    return 0;
}

D:紧张的会议室2

时间限制:10000ms
单点时限:1000ms
内存限制:256MB
描述
小Hi的公司最近员工增长迅速,同时大大小小的会议也越来越多;导致公司内的M间会议室完全不够用。
现在小Hi知道公司目前有N个会议,其中第i个会议的时间区间是(Si, Ei),权重是Wi。 注意这里时间区间可以视为是开区间,也就是说(3, 5)和(5, 6)不会被视为是同时进行的会议。
小Hi想知道利用这M间会议室最多能安排的会议的权重之和最大是多少?
输入
第一行包含两个整数N和M。
以下N行每行包含3个整数Si、Ei和Wi。
1 <= M <= N <= 250
0 <= Si < Ei <= 100000 1 <= Wi <= 1000
输出
一个整数代表答案

样例输入
5 2
1 10 10
1 5 5
6 10 3
1 2 1
2 10 8

样例输出
19

解释:最小费用流。把每个会议拆成2个点。入点和出点,直接流量为1费用为负权值。如果两个点可以连在一起就连一条边。第一个点的出点和第二个点的入点相互连接,费用为0,流量为1。两个超级汇点,一个连接全部入点,一个连接全部出点,费用为0,流量为1。最后在来一个汇点连接那个全部入点的点。然后直接跑模版就好了。

#include<iostream>
#include<vector>
#define N 666
#define INF 1000000009
using namespace std;
struct edge{
    int to,cap,cost,rev;
};
int V;
vector<edge> G[N];
int dist[N]={0};
int prevv[N],preve[N];
void add_edge(int from,int to,int cap,int cost){
    G[from].push_back(edge{to,cap,cost,G[to].size()});
    G[to].push_back(edge{from,0,-cost,G[from].size()-1});
}
int min_cost_flow(int s,int t,int f){
    int res=0;
    while(f){
        fill(dist,dist+V,INF);
        dist[s]=0;
        bool update=true;
        while(update){
            update=false;
            for(int v=0;v<V;v++){
                if(dist[v]==INF) continue;
                for(int i=0;i<G[v].size();i++){
                    edge &e=G[v][i];
                    if(e.cap>0&&dist[e.to]>dist[v]+e.cost){
                        dist[e.to]=dist[v]+e.cost;
                        prevv[e.to]=v;
                        preve[e.to]=i;
                        update=true;
                    }
                }
            }
        }
        if(dist[t]==INF){
            return -1;
        }
        int d=f;
        for(int v=t;v!=s;v=prevv[v]){
            d=min(d,G[prevv[v]][preve[v]].cap);
        }
        f-=d;
        res+=d*dist[t];
        for(int v=t;v!=s;v=prevv[v]){
            edge &e=G[prevv[v]][preve[v]];
            e.cap-=d;
            G[v][e.rev].cap+=d;
        }
    }
    return res;
}
int n=0,m=0;
int L[N]={0},R[N]={0},W[N]={0};
bool ok(int x,int y){
    if(R[x]<=L[y]) return 1;
    return 0;
}
int main(){
    cin>>n>>m;
    for(int i=1;i<=n;i++) cin>>L[i]>>R[i]>>W[i];
    V=2*n+2;
    for(int i=1;i<=n;i++){
        add_edge(2*i-1,2*i,1,-W[i]);
    }
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++){
            if(i==j) continue;
            if(ok(i,j)){
                add_edge(2*i,2*j-1,1,0);
            }
        }
    }
    for(int i=1;i<=n;i++){
        add_edge(0,2*i-1,1,0);
        add_edge(2*i,V-1,1,0);
    }
    cout<<-min_cost_flow(0,V-1,m)<<endl;
    return 0;
}

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值