1.[编程题] 牛牛找工作
时间限制:2秒
空间限制:65536K
为了找到自己满意的工作,牛牛收集了每种工作的难度和报酬。牛牛选工作的标准是在难度不超过自身能力值的情况下,牛牛选择报酬最高的工作。在牛牛选定了自己的工作后,牛牛的小伙伴们来找牛牛帮忙选工作,牛牛依然使用自己的标准来帮助小伙伴们。牛牛的小伙伴太多了,于是他只好把这个任务交给了你。
输入描述:
每个输入包含一个测试用例。
每个测试用例的第一行包含两个正整数,分别表示工作的数量N(N<=100000)和小伙伴的数量M(M<=100000)。
接下来的N行每行包含两个正整数,分别表示该项工作的难度Di(Di<=1000000000)和报酬Pi(Pi<=1000000000)。
接下来的一行包含M个正整数,分别表示M个小伙伴的能力值Ai(Ai<=1000000000)。
保证不存在两项工作的报酬相同。
输出描述:
对于每个小伙伴,在单独的一行输出一个正整数表示他能得到的最高报酬。一个工作可以被多个人选择。
输入例子1:
3 3
1 100
10 1000
1000000000 1001
9 10 1000000000
输出例子1:
100
1000
1001
#include
#include
using namespace std;
int main()
{
int N=0,M=0;
cin>>N>>M;
map<int ,int>job;
int a,b,c;
for(int i=0;icin>>a>>b;
job.insert({a,b});
}
int maxp=0;
map<int,int>::iterator it;//map是有序的。
for(it=job.begin();it!=job.end();++it)//类似背包问题,当前能力值为当前的最大值。
{
if(it->second>maxp)
maxp=it->second;
else
it->second=maxp;
}
for(int i=0;icin>>c;
it=job.upper_bound(c);//第一个大于能力值的迭代器
--it;
cout<second<return 0;
}
2.[编程题] 数对
时间限制:1秒
空间限制:32768K
牛牛以前在老师那里得到了一个正整数数对(x, y), 牛牛忘记他们具体是多少了。
但是牛牛记得老师告诉过他x和y均不大于n, 并且x除以y的余数大于等于k。
牛牛希望你能帮他计算一共有多少个可能的数对。
输入描述:
输入包括两个正整数n,k(1 <= n <= 10^5, 0 <= k <= n - 1)。
输出描述:
对于每个测试用例, 输出一个正整数表示可能的数对数量。
输入例子1:
5 2
输出例子1:
7
例子说明1:
满足条件的数对有(2,3),(2,4),(2,5),(3,4),(3,5),(4,5),(5,3)
分析:x%y>=k ==> k
#include
using namespace std;
int main()
{
long int n,k;
long int res=0;
cin>>n>>k;
int count=0;
if(k==0)
{
cout<return 0;
}
for(int y=k+1;y<=n;++y)
{
res+=n/y*(y-k);
if(n%y>=k)
{
res+=n%y-k+1;
}
}
cout<return 0;
}
3.[编程题] 被3整除
时间限制:1秒
空间限制:32768K
小Q得到一个神奇的数列: 1, 12, 123,…12345678910,1234567891011…。
并且小Q对于能否被3整除这个性质很感兴趣。
小Q现在希望你能帮他计算一下从数列的第l个到第r个(包含端点)有多少个数可以被3整除。
输入描述:
输入包括两个整数l和r(1 <= l <= r <= 1e9), 表示要求解的区间两端。
输出描述:
输出一个整数, 表示区间内能被3整除的数字个数。
输入例子1:
2 5
输出例子1:
3
例子说明1:
12, 123, 1234, 12345…
其中12, 123, 12345能被3整除。
分析:1.被3整除的数的特点为每个数字加起来能被3整除。因为r <= 1e9,是大数,不可能表示每一个数。所以分析1 12 123 1234 是等差数列。
2.
数列 长度 能否被3整除
1 1 0
12 2 1
123 3 1
1234 4 0
12345 5 1
123456 6 1
1234567 7 0
n 2*n/3 循环
#include
using namespace std;
int main()
{
long long l,r;
cin>>l>>r;
long long sum=0;
for(;l<=r;++l)
{
long long temp=(1+l)*l>>1;
if(temp%3==0)
++sum;
}
cout<#include
using namespace std;
int fun(int n)
{
return 2*n/3;
}
int main()
{
int left,right;
cin>>left>>right;
cout<1)<return 0;
}
4.[编程题] 安置路灯
时间限制:1秒
空间限制:32768K
小Q正在给一条长度为n的道路设计路灯安置方案。
为了让问题更简单,小Q把道路视为n个方格,需要照亮的地方用’.’表示, 不需要照亮的障碍物格子用’X’表示。
小Q现在要在道路上设置一些路灯, 对于安置在pos位置的路灯, 这盏路灯可以照亮pos - 1, pos, pos + 1这三个位置。
小Q希望能安置尽量少的路灯照亮所有’.’区域, 希望你能帮他计算一下最少需要多少盏路灯。
输入描述:
输入的第一行包含一个正整数t(1 <= t <= 1000), 表示测试用例数
接下来每两行一个测试数据, 第一行一个正整数n(1 <= n <= 1000),表示道路的长度。
第二行一个字符串s表示道路的构造,只包含’.’和’X’。
输出描述:
对于每个测试用例, 输出一个正整数表示最少需要多少盏路灯。
输入例子1:
2
3
.X.
11
…XX….XX
输出例子1:
1
3
分析:贪心算法,每一个灯可以最远照亮2个长度.
#include
#include
using namespace std;
int main()
{
int t;
cin>>t;
while(t--)
{
int n;
cin>>n;
string s;
cin>>s;
int num=0;
for(int i=0;iif(s[i]=='.')
{
++num;
i+=2;
}
}
cout<
5 [编程题] 牛牛的背包问题
时间限制:1秒
空间限制:32768K
牛牛准备参加学校组织的春游, 出发前牛牛准备往背包里装入一些零食, 牛牛的背包容量为w。
牛牛家里一共有n袋零食, 第i袋零食体积为v[i]。
牛牛想知道在总体积不超过背包容量的情况下,他一共有多少种零食放法(总体积为0也算一种放法)。
输入描述:
输入包括两行
第一行为两个正整数n和w(1 <= n <= 30, 1 <= w <= 2 * 10^9),表示零食的数量和背包的容量。
第二行n个正整数v[i](0 <= v[i] <= 10^9),表示每袋零食的体积。
输出描述:
输出一个正整数, 表示牛牛一共有多少种零食放法。
输入例子1:
3 10
1 2 4
输出例子1:
8
例子说明1:
三种零食总体积小于10,于是每种零食有放入和不放入两种情况,一共有2*2*2 = 8种情况。
#include
#include
#include
using namespace std;
int main()
{
int n;
long long w,sum=0;
cin>>n>>w;
vector<long long>v(n);
for(int i=0;icin>>v[i];
sum+=v[i];
}
if(sum<=w)
{
cout<<(long long )pow(2,n)<return 0;
}
vector<long long>dp;
for(int i=0;iif(v[i]<=w)
{
dp.push_back(v[i]);
int len=dp.size();
for(int j=0;j1;++j)
{
sum=0;
sum=dp[j]+dp[len-1];
if(sum<=w)
dp.push_back(sum);
}
}
}
cout<1<return 0;
}
6.[编程题] 堆棋子
小易将n个棋子摆放在一张无限大的棋盘上。第i个棋子放在第x[i]行y[i]列。同一个格子允许放置多个棋子。每一次操作小易可以把一个棋子拿起并将其移动到原格子的上、下、左、右的任意一个格子中。小易想知道要让棋盘上出现有一个格子中至少有i(1 ≤ i ≤ n)个棋子所需要的最少操作次数.
输入描述:
输入包括三行,第一行一个整数n(1 ≤ n ≤ 50),表示棋子的个数
第二行为n个棋子的横坐标x[i](1 ≤ x[i] ≤ 10^9)
第三行为n个棋子的纵坐标y[i](1 ≤ y[i] ≤ 10^9)
输出描述:
输出n个整数,第i个表示棋盘上有一个格子至少有i个棋子所需要的操作数,以空格分割。行末无空格
如样例所示:
对于1个棋子: 不需要操作
对于2个棋子: 将前两个棋子放在(1, 1)中
对于3个棋子: 将前三个棋子放在(2, 1)中
对于4个棋子: 将所有棋子都放在(3, 1)中
输入例子1:
4
1 2 4 9
1 1 1 1
输出例子1:
0 1 3 10
分析:输入的x与y并不是最优的,顺序可以调整,使输出的值为排序的。
最优点一定是在x,y上,可能在输入的点上,也可能在空白点,但是x,y一定属于(X,Y)
求解方法,枚举法,x,y构成的方格的每一个点。
#include
#include
#include
using namespace std;
void process(int n, vector<int>&x, vector<int>&y, vector<int>&ans)
{
for (int i = 0; i < n; ++i)
{
for (int j = 0; j < n; ++j)
{
vector<int>dis(n, 0);
for (int k = 0; k < n; ++k)
dis[k] = abs(x[i] - x[k]) + abs(y[j] - y[k]);
sort(dis.begin(), dis.end());
int temp = 0;
for (int l = 0; l < n; ++l)
{
temp += dis[l];
ans[l] = min(ans[l], temp);
}
}
}
}
int main()
{
int n = 0;
cin >> n;
vector<int>x(n, 0);
vector<int>y(n, 0);
vector<int>ans(n, INT_MAX);
for (int i = 0; i < n; ++i)cin >> x[i];
for (int i = 0; i < n; ++i)cin >> y[i];
process(n, x, y, ans);
for (int i = 0; i < n; ++i)
cout << ans[i] << " ";
system("pause");
return 0;
}
7.[编程题] 牛牛打响指
时间限制:1秒
空间限制:32768K
牛牛在地上捡到了一个手套,他带上手套发现眼前出现了很多个小人,当他打一下响指,这些小人的数量就会发生以下变化:如果小人原本的数量是偶数那么数量就会变成一半,如果小人原本的数量是奇数那么数量就会加一。现在牛牛想考考你,他要打多少次响指,才能让小人的数量变成1。
输入描述:
每个输入包含一个测试用例。
输入的第一行包括一个正整数,表示一开始小人的数量N(1<=N<=10^100)。
输出描述:
对于每个用例,在单独的一行中输出牛牛需要打多少次响指才能让小人的数量变成1。
输入例子1:
10000
输出例子1:
20
#include
#include
using namespace std;
int main()
{
string data;
cin >> data;
data='0'+data;
int right=data.size()-1,left=1,ans=0,now;
for(int i=0;i<=right;++i)
data[i]-='0';
while(data[right]!=1 || left!=right)
{
++ans;
if(data[right]%2==1)//odd
{
++data[right];
now=right;
while(data[now]==10)
{
data[now]=0;
data[now-1]+=1;
now-=1;
if(nowelse
{
for(int i=left;i<=right;++i)
{
if(data[i]%2)
data[i+1]+=10;
data[i]=data[i]/2;
}
if(data[left]==0)
left+=1;
}
}
cout << ans << endl;
return 0;
}
8.[编程题] 牛牛数星星
时间限制:1秒
空间限制:32768K
一闪一闪亮晶晶,满天都是小星星,牛牛晚上闲来无聊,便躺在床上数星星。
牛牛把星星图看成一个平面,左上角为原点(坐标为(1, 1))。现在有n颗星星,他给每颗星星都标上坐标(xi,yi),表示这颗星星在第x行,第y列。
现在,牛牛想问你m个问题,给你两个点的坐标(a1, b1)(a2,b2),表示一个矩形的左上角的点坐标和右下角的点坐标,请问在这个矩形内有多少颗星星(边界上的点也算是矩形内)。
输入描述:
第一行输入一个数字n(1≤n≤100000),表示星星的颗数。
接下来的n行,每行输入两个数xi和yi(1≤xi,yi≤1000),表示星星的位置。
然后输入一个数字m(1≤m≤100000), 表示牛牛询问问题的个数。
接下来m行,每行输入四个数字a1,b1,a2,b2(1≤a1<a2≤1000), (1≤b1<b2≤1000)
题目保证两颗星星不会存在于同一个位置。
输出描述:
输出一共包含m行,每行表示与之对应的每个问题的答案。
输入例子1:
4
1 1
2 2
3 3
1 3
4
1 1 2 2
1 1 3 3
2 2 3 3
1 2 2 3
输出例子1:
2
4
2
2
分析:
从数据规模可以看到,我们一共有10万颗星星以及最多10万次查询,如果我们每次查询都把给出的范围内遍历一遍的话肯定会超时。那么,我们就需要换一种方法。因为我们只需要得到一个矩形范围内的星星的数量,我们就可以先跑一遍整个数据范围,找到这个点的左上方向一共有多少颗星星,并把它标记出来。那么,我们要得到的矩形范围内的星星数量就变为了这个矩形右下角的点的值减去这个矩形左下角左边那个点的值再减去这个矩形右上角上面那个点的值再加上这个矩形左上角的左上边那个点的值(可以想象一下容斥定理)。那么,我们只需要遍历一次1000*1000的地图就行了,每个查询可以O(1)来获取。
#include
using namespace std;
const int maxm=1e3+5;
int num[maxm][maxm];
int star[maxm][maxm];
int main()
{
int n=0;
cin>>n;
int x=0,y=0;
for(int i=0;icin>>x>>y;
star[x][y]+=1;
}
for(int i=1;ifor(int j=1;j1][j]+num[i][j-1]-num[i-1][j-1]+star[i][j];
int m=0,a1=0,a2=0,b1=0,b2=0;
cin>>m;
for(int i=0;icin>>a1>>b1>>a2>>b2;
cout<1][b2]-num[a2][b1-1]+num[a1-1][b1-1]<return 0;
}
9.[编程题] 牛牛偶像养成记
时间限制:1秒
空间限制:32768K
为了拯救因入学人数骤降,面临废弃的学校,牛牛决定成为偶像啦。当然,作为一个偶像,肯定是要上台表演的。
已知牛牛拿到了n个上台表演的机会,第i次表演的上台时间为ti时刻,需要表演mi这么长的时间。
牛牛为了提高自己的知名度,肯定要取得最多的上场次数。请问,牛牛最多能上场多少次呢?
输入描述:
第一行输入一个数字n(1≤n≤100000),表示牛牛获得的上台表演的机会
接下来n行,每行输入两个数字ti(1≤ti≤108)和mi(1≤mi≤108), 表示第i次表演机会的上台时间和该次表演需要的总时间(表演途中不能中断表演退出)。
输出描述:
牛牛最多能上场的次数。
输入例子1:
3
1 2
3 2
5 2
输出例子1:
3
分析:尽量早结束,这样才能更多的时间安排新的。
#include
#include
using namespace std;
const int maxm=100005;
struct node
{
int start,end;
};
bool cmp(node x,node y)
{
if(x.end != y.end)
return x.endelse
return x.startint n,m;
int main()
{
cin>>n;
for(int i=0;icin>>data[i].start>>m;
data[i].end=data[i].start+m;
}
sort(data,data+n,cmp);
int count=0,t=0;
for(int i=0;iif(t<=data[i].start)
{
count++;
t=data[i].end;
}
}
cout<return 0;
}