@wsndy-xx
2018-06-25T01:04:12.000000Z
字数 7436
阅读 1750
题解
题意:给定一个十进制正整数N,写下从1开始,到N的所有正数,计算出其中出现所有1的个数
思路:分块打表或者分类讨论
#include<stdio.h>long long int Count(long long int n){//1的个数long long int count = 0;//当前位long long int Factor = 1;//低位数字long long int LowerNum = 0;//当前位数字long long int CurrNum = 0;//高位数字long long int HigherNum = 0;if(n <= 0){return 0;}while(n / Factor != 0){//低位数字LowerNum = n - (n / Factor) * Factor;//当前位数字CurrNum = (n / Factor) % 10;//高位数字HigherNum = n / (Factor * 10);//如果为0,出现1的次数由高位决定if(CurrNum == 0){//等于高位数字 * 当前位数count += HigherNum * Factor;}//如果为1,出现1的次数由高位和低位决定else if(CurrNum == 1){//高位数字 * 当前位数 + 低位数字 + 1count += HigherNum * Factor + LowerNum + 1;}//如果大于1,出现1的次数由高位决定else{//(高位数字+1)* 当前位数count += (HigherNum + 1) * Factor;}//前移一位Factor *= 10;}return count;}int main(){long long int a;while(scanf("%lld",&a) != EOF){printf("%lld\n",Count(a));}return 0;}
题意:有编号1-n的n个格子,机器人从1号格子顺序向后走,一直走到n号格子,并需要从n号格子走出去。机器人有一个初始能量,每个格子对应一个整数A[i],表示这个格子的能量值。如果A[i] > 0,机器人走到这个格子能够获取A[i]个能量,如果A[i] < 0,走到这个格子需要消耗相应的能量,如果机器人的能量 < 0,就无法继续前进了。问机器人最少需要有多少初始能量,才能完成整个旅程。
思路:判断最小前缀和
#include <iostream>#include <cstdio>#include <algorithm>#define LL long longconst int N = 50010;LL A[N], Minn;int n;int main() {std:: cin >> n;for(int i = 1; i <= n; i ++) std:: cin >> A[i];Minn = A[1];for(int i = 2; i <= n; i ++) {A[i] += A[i - 1];Minn = std:: min(A[i], Minn);}if(Minn >= 0) std:: cout << 0;else std:: cout << -Minn;return 0;}
题意:有一口井,井的高度为N,每隔1个单位它的宽度有变化。现在从井口往下面扔圆盘,如果圆盘的宽度大于井在某个高度的宽度,则圆盘被卡住(恰好等于的话会下去)。
盘子有几种命运:1、掉到井底。2、被卡住。3、落到别的盘子上方。
盘子的高度也是单位高度。给定井的宽度和每个盘子的宽度,求最终落到井内的盘子数量。
思路:前缀最小值优化,对每一个盘子找到最优的位置
#include <iostream>#include <cstdio>#include <algorithm>const int N = 50010;int A[N], B[N], At, Bt;int Minn[N]; //前缀最小值int main() {std:: cin >> At >> Bt;for(int i = 1; i <= At; i ++) std:: cin >> A[i];for(int i = 1; i <= Bt; i ++) std:: cin >> B[i];Minn[1] = A[1];for(int i = 2; i <= At; i ++) Minn[i] = std:: min(Minn[i - 1], A[i]);int down = At, i;for(i = 1; i <= Bt && down > 0; i ++) {if(Minn[down] >= B[i]) {down --; continue;}while(Minn[down] < B[i] && down) down --;if(down == 0) break;down --;}std:: cout << i - 1;return 0;}
题意: n个人,已知每个人体重。独木舟承重固定,每只独木舟最多坐两个人,可以坐一个人或者两个人。显然要求总重量不超过独木舟承重,假设每个人体重也不超过独木舟承重,问最少需要几只独木舟?
思路: 排序后贪心
#include <iostream>#include <cstdio>#include <algorithm>const int N = 10010;int A[N], n, m;int main() {std:: cin >> n >> m;for(int i = 1; i <= n; i ++) std:: cin >> A[i];std:: sort(A + 1, A + n + 1);int l = 1, r = n, js = 0, Answer = 0;while(js != n) {if(A[l] + A[r] <= m) l ++, r --, js += 2, Answer ++;else r --, js ++, Answer ++;if(l == r) {Answer ++; break;}}std:: cout << Answer;return 0;}
题意:平面上有N个点,任意2个点确定一条直线,求出所有这些直线中,斜率最大的那条直线所通过的两个点。
(点的编号为1-N,如果有多条直线斜率相等,则输出所有结果,按照点的X轴坐标排序,正序输出。数据中所有点的X轴坐标均不相等,且点坐标为随机。)
思路: 暴力判断
#include <iostream>#include <cstdio>#include <algorithm>#include <cmath>const int N = 10010;const double eps = 1e-10;struct Node {int x, y;} Point[N];int n, Ans_js;Node Ans[N];inline double Get_k(int a, int b) {return (double)(Point[a].y - Point[b].y) / (double)(Point[a].x - Point[b].x);}int main() {std:: cin >> n;for(int i = 1; i <= n; i ++) std:: cin >> Point[i].x >> Point[i].y;double Max_k = 0;for(int i = 1; i <= n; i ++)for(int j = i + 1; j <= n; j ++) {double Now_k = Get_k(i, j);if(Now_k > Max_k) {Max_k = Now_k; Ans_js = 0;if(Point[i].x < Point[j].x) Ans[++ Ans_js].x = i, Ans[Ans_js].y = j;else Ans[++ Ans_js].x = j, Ans[Ans_js].y = i;} else if(Now_k == Max_k) {if(Point[i].x < Point[j].x) Ans[++ Ans_js].x = i, Ans[Ans_js].y = j;else Ans[++ Ans_js].x = j, Ans[Ans_js].y = i;}}for(int i = 1; i <= Ans_js; i ++) std:: cout << Ans[i].x << " " << Ans[i].y << "\n";return 0;}
题意:现有的统计工具只能统计某一个窗口中,用户的满意程度的均值。夹克老爷想让你为统计工具添加一个新feature,即在统计均值的同时,计算窗口中满意程度的标准差和中位数(均值需要向下取整)。
思路:线段树维护
#include<stdio.h>#include<string.h>#include<math.h>#include<queue>#include<algorithm>using namespace std;#define LL long longdouble he[2];int shu;struct node{int l,r,shu;}PP[300];void creat(int l,int r,int x){PP[x].l=l;PP[x].r=r;PP[x].shu=0;if (l==r) return ;int m=(l+r)>>1;creat(l,m,x*2);creat(m+1,r,x*2+1);}void add(int wei,int x){PP[x].shu++;if (PP[x].l==PP[x].r) return ;int m=(PP[x].l+PP[x].r)>>1;if (wei>m) add(wei,x*2+1);else add(wei,x*2);}void jian(int wei,int x){PP[x].shu--;if (PP[x].l==PP[x].r) return ;int m=(PP[x].l+PP[x].r)>>1;if (wei>m) jian(wei,x*2+1);else jian(wei,x*2);}int query(int ll,int x){if (PP[x].l==PP[x].r)return PP[x].l;else if (PP[x*2].shu<ll)query(ll-PP[x*2].shu,x*2+1);elsequery(ll,x*2);}int main(){queue<int> que;int n,k;scanf("%d%d",&n,&k);int s=0,a,b;shu=0;creat(0,100,1);while (n--){scanf("%d",&a);switch(a){case 1:if (shu==k){b=que.front();que.pop();he[0]-=b;he[1]-=b*b;jian(b,1);}else shu++;scanf("%d",&b);que.push(b);he[0]+=b;he[1]+=b*b;add(b,1);break;case 2:printf("%d.00\n",((int)he[0])/shu);break;case 3:printf("%.2lf\n",he[1]/shu-(he[0]/shu)*(he[0]/shu));break;case 4:if (shu%2==0){a=query(shu/2,1);b=query(shu/2+1,1);printf("%.2lf\n",(a+b)/2.0);}else{b=query(shu/2+1,1);printf("%.2lf\n",(double)b);}break;}}return 0;}
题意:有N只兔子,每只有一个血量B[i],需要用箭杀死免子。有M种不同类型的箭可以选择,每种箭对兔子的伤害值分别为D[i],价格为P[i](1 <= i <= M)。假设每种箭只能使用一次,每只免子也只能被射一次,计算要消灭地图上的所有兔子最少需要多少Q币。如不能杀死所有兔子,请输出No Solution。
特别说明:1、当箭的伤害值大于等于兔子的血量时,能将兔子杀死;2、血量B[i],箭的伤害值D[i],箭的价格P[i],均小于等于100000。
思路:对血量贪心找到最合适的剑,优先队列优化
#include <iostream>#include <cstdio>#include <algorithm>#include <cmath>#include <queue>using namespace std;const int N = 50010;int B[N];struct Node {int hit, money;}A[N];int n, m;bool operator <(Node a, Node b) {return a.money > b.money;}bool cmp_1(int a, int b) {return a > b;}bool cmp_2(Node a, Node b) {return a.hit > b.hit;}priority_queue <Node> Q;int main() {cin >> n >> m;if(n > m) {cout << "No Solution"; return 0;}for(int i = 1; i <= n; i ++) cin >> B[i];for(int i = 1; i <= m; i ++) cin >> A[i].hit >> A[i].money;std:: sort(B + 1, B + n + 1, cmp_1);std:: sort(A + 1, A + m + 1, cmp_2);int Answer = 0;for(int i = 1, j = 1; i <= n; i ++) { // 对于每一只兔子寻找合适的炮for(; j <= m; j ++)if(A[j].hit >= B[i]) Q.push(A[j]);else break;if(!Q.empty()) {Node topp = Q.top();Q.pop();Answer += topp.money;} else {cout << "No Solution"; return 0;}}std:: cout << Answer;return 0;}
题意:一个长度为M的正整数数组A,表示从左向右的地形高度。测试一种加农炮,炮弹平行于地面从左向右飞行,高度为H,如果某处地形的高度大于等于炮弹飞行的高度H(A[i] >= H),炮弹会被挡住并落在i - 1处,则A[i - 1] + 1。如果H <= A[0],则这个炮弹无效,如果H > 所有的A[i],这个炮弹也无效。现在给定N个整数的数组B代表炮弹高度,计算出最后地形的样子。
例如:地形高度A = {1, 2, 0, 4, 3, 2, 1, 5, 7}, 炮弹高度B = {2, 8, 0, 7, 6, 5, 3, 4, 5, 6, 5},最终得到的地形高度为:{2, 2, 2, 4, 3, 3, 5, 6, 7}。
思路:对于每一个高度,预处理出应该落在哪里,对于每一发炮弹下落后影响的高度为 级别的,可以判断后调整,预处理时可以前缀最大值优化。
#include <bits/stdc++.h>const int N = 50010;int n, m;int A[N], B[N];int hight[N * 22], Max_hight;int Maxn[N];int Answer[N];int main() {std:: cin >> n >> m;for(int i = 1; i <= n; i ++) std:: cin >> A[i];for(int i = 1; i <= m; i ++) std:: cin >> B[i];for(int i = 1; i <= m; i ++) Max_hight = std:: max(Max_hight, B[i]);for(int i = 1; i <= n; i ++) Maxn[i] = std:: max(Maxn[i - 1], A[i]); // 前缀最大值for(int i = 1; i <= n; i ++)if(Maxn[i] != Maxn[i - 1])for(int j = Maxn[i - 1] + 1; j <= Maxn[i]; j ++)hight[j] = i;for(int j = Maxn[n] + 1; j <= Max_hight; j ++) hight[j] = n + 2;for(int i = 1; i <= m; i ++) {int H = hight[B[i]];if(H > n || !H) continue ;A[H - 1] ++;hight[A[H - 1]] = std:: min(hight[A[H - 1]], H - 1);hight[A[H - 1] - 1] = std:: min(hight[A[H - 1] - 1], H - 1);}for(int i = 1; i <= n; i ++) std:: cout << A[i] << "\n";return 0;}
题意:有N行M列的正方形盒子。每个盒子有三种状态0, -1, +1。球从盒子上边或左边进入盒子,从下边或右边离开盒子。规则:
如果盒子的模式是-1,则进入它的球从下面出去。(方向变为向下)
如果盒子的模式是+1,则进入它的球从右面出去。 (反向变为向右)
如果盒子的模式是0, 则进入它的球方向不变。从上面进入的,从下面出去,从左面进入的,从右面出去。
思路:每个格子在经过后会变为相反数,经过一个格子的球的数目可以由该格子上方的格子向下走的数量 + 该格子左边的格子向右走的数量相加得到,该格子向右或向下走的数量又可以由该格子的初始状态决定
因此就可以完美递推啦
#include <bits/stdc++.h>const int N = 1e3 + 10;int A[N][N];int n, m;long long k, Sum[N][N][2];inline long long read() {long long x; char c = getchar();while(c < '0' || c > '9') c = getchar();while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();return x;}int main() {std:: cin >> m >> n >> k;for(int i = 1; i <= n; i ++) for(int j = 1; j <= m; j ++) std:: cin >> A[i][j];for(int i = 1; i <= n; i ++) {for(int j = 1; j <= m; j ++) {if(i == 1 && j == 1) {if(A[1][1] == 1) Sum[1][1][1] = (k + 1) >> 1, Sum[1][1][0] = k >> 1;else if(A[1][1] == -1) Sum[1][1][0] = (k + 1) >> 1, Sum[1][1][1] = k >> 1;else Sum[1][1][0] = k;} else {long long tmp = Sum[i - 1][j][0] + Sum[i][j - 1][1];if(!A[i][j]) Sum[i][j][0] = Sum[i - 1][j][0], Sum[i][j][1] = Sum[i][j - 1][1];else if(A[i][j] == 1) Sum[i][j][1] = (tmp + 1) >> 1, Sum[i][j][0] = tmp >> 1;else Sum[i][j][0] = (tmp + 1) >> 1, Sum[i][j][1] = tmp >> 1;}}}std:: cout << Sum[n][m][0];return 0;}/*3 2 4-1 0 -11 0 0*/