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;
}