【题目】
以下的10行数据,每行有10个整数,请你求出它们的乘积的末尾有多少个零?ios
5650 4542 3554 473 946 4114 3871 9073 90 4329
2758 7949 6113 5659 5245 7432 3051 4434 6704 3594
9937 1173 6866 3397 4759 7557 3070 2287 1453 9899
1486 5722 3135 1170 4014 5510 5120 729 2880 9019
2049 698 4582 4346 4427 646 9742 7340 1230 7683
5693 7015 6887 7381 4172 4341 2909 2027 7355 5649
6701 6645 1671 5978 2704 9926 295 3125 3878 6785
2066 4247 4800 1578 6652 4616 1113 6205 3264 2915
3966 5291 2904 1285 2193 1428 2265 8730 9436 7074
689 5510 8243 6114 337 4096 8199 7313 3685 211程序员
注意:须要提交的是一个整数,表示末尾零的个数。数组
【思路】
看这些数当中2与5有多少对,将每个数的因数中的2的个数统计出来,5同理,而后取二者的最小值即为对数。
【题解】测试
#include<cstdio> #include<cmath> #include<iostream> #include<algorithm> using namespace std; int main() { int num[100] = { 5650,4542,3554,473,946,4114,3871,9073,90,4329, 2758,7949,6113,5659,5245,7432,3051,4434,6704,3594, 9937,1173,6866,3397,4759,7557,3070,2287,1453,9899, 1486,5722,3135,1170,4014,5510,5120,729,2880,9019, 2049,698,4582,4346,4427,646,9742,7340,1230,7683, 5693,7015,6887,7381,4172,4341,2909,2027,7355,5649, 6701,6645,1671,5978,2704,9926,295,3125,3878,6785, 2066,4247,4800,1578,6652,4616,1113,6205,3264,2915, 3966,5291,2904,1285,2193,1428,2265,8730,9436,7074, 689,5510,8243,6114,337,4096,8199,7313,3685,211 }; int two = 0, five = 0; for (int i = 0; i < 100; i++) { int t = num[i]; while (t) { if (t % 2 == 0) { t /= 2; two++; } else break; } t = num[i]; while (t) { if (t % 5 == 0) { t /= 5; five++; } else break; } } cout << min(two, five) << endl; return 0; }
【题目】
x星球的居民脾气不太好,但好在他们生气的时候惟一的异常举动是:摔手机。
各大厂商也就纷纷推出各类耐摔型手机。x星球的质监局规定了手机必须通过耐摔测试,而且评定出一个耐摔指数来,以后才容许上市流通。
x星球有不少高耸入云的高塔,恰好能够用来作耐摔测试。塔的每一层高度都是同样的,与地球上稍有不一样的是,他们的第一层不是地面,
而是至关于咱们的2楼。
若是手机从第7层扔下去没摔坏,但第8层摔坏了,则手机耐摔指数=7。
特别地,若是手机从第1层扔下去就坏了,则耐摔指数=0。
若是到了塔的最高层第n层扔没摔坏,则耐摔指数=n
为了减小测试次数,从每一个厂家抽样3部手机参加测试。
某次测试的塔高为1000层,若是咱们老是采用最佳策略,在最坏的运气下最多须要测试多少次才能肯定手机的耐摔指数呢?
请填写这个最多测试次数。
注意:须要填写的是一个整数,不要填写任何多余内容。
【思路】
设这个测试次数为k次,3部手机一共测试k次能够测出耐摔指数。既然有k次机会,咱们不妨就把第1部手机先从第k层楼摔下去。
若是第1部手机摔死了,那么第2部手机剩下k-1次机会,能够从1~k-1层来测试。若是第1部手机没摔死,那么它还剩下k-1次机会,
那咱们下次就能够从第k+(k-1)层楼摔。若是它这一次摔死了,那么第2部手机还有k-2次机会,就能够从k+1~k+(k-1)-1层来测
试。若是第1部手机在第k+(k-1)层摔下来后仍旧活下来了,那么它还有k-2次机会,在下次就能够从第k+(k-1)+(k-2)层摔。以
此类推,必定能够在k次内测出耐摔指数。
那么有人就要说了,你这里只说了2部手机,但是咱们有3部手机啊。其实状况是同样的,假如咱们有n部手机m层楼,第1部手机在第
k层摔死了,那么接下来要测试的就是n-1部手机k-1层楼的状况,若是没摔死,就测试n部手机m-k层楼的状况(人会有主观意识以为
楼层越高越容易摔死,可是那不必定,手机也有可能到1000层都摔不死呢,因此测试状况的时候咱们能够只看层数,k+1m和1m-k是同样的)。
综上所述,咱们能够推出动态转移方程:dp[i][j]表示i部手机j层楼的最少测试次数,dp[i][j]=max(dp[i-1][k-1],dp[i][j-k])+1,
k∈[1,j-1](这里取max是由于i部手机j层楼有dp[i][j]次测试机会,咱们必须确保在这个次数内全部状况的耐摔指数都要能被测出来,
若是取了较小的那个,次数多于它的状况就无法确保被测试出来)。咱们一开始在给dp数组初始化的时候,能够所有初始化为它的最坏状况,
j层楼的最坏测试次数是j次,就是每层楼都要摔一次,那么咱们这里用了最佳策略后,次数就应该小于等于这个值,方程就能够变化为:
dp[i][j]=min(dp[i][j],max(dp[i-1][k-1],dp[i][j-k])+1),k∈[1,j-1]。
【题解】优化
#include <iostream> using std::cout; using std::endl; int dp[5][1005]; void solve(int phone, int floor) { for(int i = 1; i <= phone; i++) for(int j = 1; j <= floor; j++) dp[i][j] = j; // for(int i = 2; i <= phone; i++) // for(int j = 1; j <= floor; j++) for(int k = 1; k < j; k++) // dp[i][j] = std::min(dp[i][j], std::max(dp[i-1][k-1], dp[i][j-k]) + 1); } int main() { solve(3, 1000); cout << dp[3][1000] << endl; return 0; }
【题目】
快速排序代码补全,这里直接给出完整代码,该题快排采用递归实现。
【题解】ui
#include <iostream> #include <vector> #include <list> #include <numeric> #include <string> #include <stdio.h> #include <queue> #include <string.h> #include <cmath> #include <algorithm> #include <set> using std::endl; using std::cout; void quickSort(int *arr, int begin, int end) { if(begin < end) { int temp = arr[begin]; int i = begin; int j = end; while(i < j) { while(i < j && arr[j] > temp) j--; arr[i] = arr[j]; while(i < j && arr[i] <= temp) i++; arr[j] = arr[i]; } arr[i] = temp; // 递归排序基准数两边子集 quickSort(arr, begin, i-1); quickSort(arr, i+1, end); } else return; } int main() { int num[10] = {23, 14, 5, 7, 29, 50, 11, 33, 10, 8}; cout << "排序前: " << endl; for(int i = 0; i < 10; i++) cout << num[i] << " "; cout << endl; quickSort(num, 0, 9); cout << "排序后: " << endl; for(int i = 0; i < 10; i++) cout << num[i] << " "; cout << endl; return 0; }
【题目】
给定三个整型数组
A = [A1, A2, … An]
B = [ … ]
C = [ … ]
统计有多少个三元组(i, j, k)知足:
一、 1 <= (i, j, k) <= n
二、 Ai < Bj < Ckspa
输入示例:
3
1 1 1
2 2 2
3 3 3.net
输出示例:
27
【题解】3d
#include <iostream> #include <vector> #include <list> #include <numeric> #include <string> #include <stdio.h> #include <queue> #include <string.h> #include <cmath> #include <algorithm> #include <set> using std::endl; using std::cout; int main() { using std::cin; using std::sort; int n, flag = 0; long long ans = 0; const int N = 10005; cin >> n; int *A = new int[n]; int *B = new int[n]; int *C = new int[n]; for(int i = 0; i < n; i++) cin >> A[i]; for(int i = 0; i < n; i++) cin >> B[i]; for(int i = 0; i < n; i++) cin >> C[i]; // // 暴力 // for(int i = 0; i < n; i++) // for(int j = 0; j < n; j++) // for(int k = 0; k < n; k++) // { // if(A[i] < B[j] && B[j] < C[k]) // ans++; // } // 优化 int temp = 0; sort(A, A + n); sort(B, B + n); sort(C, C + n); for(int i = 0; i < n; i++) { for(int j = temp; j < n; j++) { if(B[j] > A[i]) { if(!flag) { temp = j; flag = 1; } ans += C + n - std::upper_bound(C, C+n, B[j]); } } flag = 0; } cout << ans << endl; delete[] A, B, C; return 0; }
【题目】
以下图所示的螺旋折线通过平面上全部整点刚好一次
对于整点(X, Y),咱们定义它到原点的距离dis(X, Y)是从原点到(X, Y)的螺旋折线段的长度。
例如dis(0, 1)=3, dis(-2, -1)=9
给出整点坐标(X, Y),你能计算出dis(X, Y)吗?
日志
输入样例:
0 1
输出样例:
3
测试数据:
输入——>
1 0
2 0
3 0
-1 0
2 2
3 2
-1 2
输出——>
5 18 39 1 16 37 13
【思路】
分类讨论+找规律,先找四个象限的角点的规律,如图能够看到第一二四象限的角点各自与x轴y轴都造成了一个小正方形,
设这个小边长为t。第一象限的角点规律是4t2,当x>y时,t就是x,那么在这个范围内的点就是4t2+(x-y);
当x<y时,t就是y,那么在这个范围内的点就是4t^2-(y-x)。第二象限的角点规律是2t(2t-1),当abs(x)>y时,
t就是-x,那么在这个范围内的点就是2t(2t-1)-(-x-y);当abs(x)<y时,t就是y,那么在这个范围内的点就是
2t(2t-1)+(y-(-x))。第四象限的角点规律是2t(2t+1),当x>abs(y)时,t就是x,那么在这个范围内的点就是
2t(2t+1)-(x-(-y));当x<abs(y)时,t就是-y,那么在这个范围内的点就是2t(2t+1)+(-y-x)。第三象限就
有点复杂了,它的角点规律是(-x-y)^2,因为在第三象限造成的是个小矩形,因此咱们并很差找矩形,可是至少可
以看出这个角点上x和y的差值为1,这里不用t表示边长,这里用t表示角点的(-x-y)是多少,当abs(x)>abs(y)时,
t=-x-x-1,那么这个范围内的点就是t2+(-x-1-(-y)),不然,t=-y-y+1,范围内的点就是t2-(-y+1-(-x))。
【题解】
#include <iostream> #include <vector> #include <list> #include <numeric> #include <string> #include <stdio.h> #include <queue> #include <string.h> #include <cmath> #include <algorithm> #include <set> using std::endl; using std::cout; int main() { using std::max; long long x, y, t, ans = 0; std::cin >> x >> y; // 四种状况 if(x >= 0 && y >= 0) { t = max(x, y); ans = 4 * t * t + x - y; } else if(x < 0 && y >= 0) { t = max(-x, y); ans = 2 * t * (2 * t - 1) + x + y; } else if(x >=0 && y < 0) { t = max(x, -y); ans = 2 * t * (2 * t + 1) - x - y; } else { if(x < y) t = -x - x - 1; else t = -y - y + 1; ans = t * t + - x - 1 + y; } cout << ans << endl; return 0; }
【题目】
小明维护着一个程序员论坛。如今他收集了一份"点赞"日志,日志共有N行。其中每一行的格式是:
ts id
表示在ts时刻编号id的帖子收到一个"赞"。
如今小明想统计有哪些帖子曾经是"热帖"。若是一个帖子曾在任意一个长度为D的时间段内收到很多于K个赞,小明就认为这个帖子曾是"热帖"。
具体来讲,若是存在某个时刻T知足该帖在[T, T+D)这段时间内(注意是左闭右开区间)收到很多于K个赞,该帖就曾是"热帖"。
给定日志,请你帮助小明统计出全部曾是"热帖"的帖子编号。
输入格式:
第一行包含三个整数N、D和K。
如下N行每行一条日志,包含两个整数ts和id。
输出格式:
按从小到大的顺序输出热帖id。每一个id一行。
输入样例:
7 10 2
0 1
0 10
10 10
10 1
9 1
100 3
100 3
输出样例:
1
3
【思路】
把每一个日志得到的点赞信息存储好,按时间排序,用尺取法r在前l在后,当点赞数大于等于k,
判断时间间隔,不知足就l往前取,r继续日后取,直到点赞数大于等于k执行相同判断.
用set容器存储id方便访问而且能够达到输入去重的目的。
【题解】
#include <iostream> #include <vector> #include <list> #include <numeric> #include <string> #include <stdio.h> #include <queue> #include <string.h> #include <cmath> #include <algorithm> #include <set> using std::endl; using std::cout; using std::vector; using std::set; #define N 100005 vector<int> t[N]; set<int> s; int n, d, k; bool judge(int x) { int len = t[x].size(); if(len < k) return false; std::sort(t[x].begin(), t[x].end()); int l = 0, r = 0, sum = 0; while(l <= r && r < len) { sum++; if(sum >= k) { if(t[x][r] - t[x][l] < d) return true; else { l++; sum--; } } r++; } return false; } int main() { std::cin >> n >> d >> k; for(int i = 0; i < n; i++) { int id, ts; std::cin >> ts >> id; t[id].push_back(ts); s.insert(id); } for(auto it = s.begin(); it != s.end(); it++) { if(judge(int(*it))) cout << *it << endl; } return 0; }
【题目】
你有一张某海域NxN像素的照片,".“表示海洋、”#"表示陆地,以下所示:
… …
.##…
.##…
…##.
…####.
…###.
… …
其中"上下左右"四个方向上连在一块儿的一片陆地组成一座岛屿。例如上图就有2座岛屿。 ?
因为全球变暖致使了海面上升,科学家预测将来几十年,岛屿边缘一个像素的范围会被海水淹没。
具体来讲若是一块陆地像素与海洋相邻(上下左右四个相邻像素中有海洋),它就会被淹没。 ?
例如上图中的海域将来会变成以下样子:
… …
… …
… …
… …
…#…
… …
… …
请你计算:依照科学家的预测,照片中有多少岛屿会被彻底淹没。
输入格式:
7
… …
.##…
.##…
…##.
…####.
…###.
… …
输出格式:
1
【解题思路】
BFS,找出一共有多少个连通块(岛屿定义方法即为连通块定义),判断连通块若是每一个"#“都连着哪怕一个”.",那么这样的岛屿会彻底消失,只要有一个"#“的上下左右都不是”."的时候,就不会彻底消失。
【题解】
#include <iostream> #include <vector> #include <list> #include <numeric> #include <string> #include <stdio.h> #include <queue> #include <string.h> #include <cmath> #include <algorithm> #include <set> using std::endl; using std::cout; using std::queue; using std::cin; #define N 1000 char a[N][N]; int n, vis[N][N]; int dir[4][2] = {{-1, 0}, {0, -1}, {0, 1}, {1, 0}}; class point { public: int x, y; point(int a, int b) { x = a; y = b; } }; int bfs(int x, int y) // 用来判断每一个连通块是否存在符合条件的"#" { queue<point> q; q.push(point(x, y)); int left = 0; while(!q.empty()) { point p = q.front(); q.pop(); int cnt = 0; for(int i = 0; i < 4; i++) // 四方向判断 { int dx = p.x + dir[i][0], dy = p.y + dir[i][1]; if(dx < 0 || dx >= n || dy < 0 || dy >= n) // 边界判断 continue; if(a[dx][dy] == '#') { cnt++; if(!vis[dx][dy]) { vis[dx][dy] = 1; q.push(point(dx, dy)); } } } if(cnt == 4) left++; } return left; // 返回一个岛(连通块)淹没后残留的"#"数量 } int main() { int i, j, ans = 0; cin >> n; for(i = 0; i < n; i++) for(j = 0; j < n; j++) cin >> a[i][j]; memset(vis, 0, sizeof(vis)); for(i = 0; i < n; i++) for(j = 0; j < n; j++) if(a[i][j] == '#' && !vis[i][j]) { vis[i][j] = 1; if(!bfs(i, j)) ans++; } cout << ans << endl; return 0; }
【题目】
给定N个整数A1, A2, … AN。请你从中选出K个数,使其乘积最大。
请你求出最大的乘积,因为乘积可能超出整型范围,你只需输出乘积除以1000000009的余数。
注意,若是X<0, 咱们定义X除以1000000009的余数是负(-X)除以1000000009的余数。
即:0-((0-x) % 1000000009)
输入格式:
第一行包含两个整数N和K。
如下N行每行一个整数Ai。
对于40%的数据,1 <= K <= N <= 100
对于60%的数据,1 <= K <= 1000
对于100%的数据,1 <= K <= N <= 100000 -100000 <= Ai <= 100000
输出格式:
一个整数,表示答案。
输入样例:
5 3
-100000
-10000
2
100000
10000
输出样例:
999100009
再例如:
输入样例:
5 3
-100000
-100000
-2
-100000
-100000
输出样例:
-999999829
【解题思路】
把这些数按照绝对值从大到小排序:
①当n==k时,只能全选了
②若是n个数全是正数,选择前k个便可
③若是n个数全是负数,若是k是偶数,选择前k个便可;若是k是奇数,选择后k个便可
④剩下的状况就是有正有负了,先看前k个数,若是负数个数为偶数,选择前k个便可;若是负数个数为奇数,则比较前面最后一个负数与后面第一个负数的乘积和前面最后一个正数与后面第一个正数的乘积哪一个大,取大的便可
参考:https://blog.csdn.net/ryo_218/article/details/79822728
【题解】
#include<cstdio> #include<cstdlib> #include<cstring> #include<cmath> #include<iostream> #include<algorithm> #include<string> #include<vector> #include<queue> #include<map> #include<set> using namespace std; #define N 100000 #define MOD 1000000009 struct number { int sign; long long num; }a[N]; bool cmp(const number &x,const number &y) { return x.num>y.num; } int main() { int n,k,cnt=0; long long t,ans=1; cin>>n>>k; for(int i=0;i<n;i++) { cin>>t; if(t<0) { a[i].sign=-1; a[i].num=-t; cnt++; } else { a[i].sign=1; a[i].num=t; } } if(n==k) { for(int i=0;i<k;i++) ans=(ans*a[i].num)%MOD; if(cnt&1) ans=-ans; } else { sort(a,a+n,cmp); if(cnt==n)//全是负数 { if(k&1) { for(int i=n-1;i>n-1-k;i--) ans=(ans*a[i].num)%MOD; ans=-ans; } else { for(int i=0;i<k;i++) ans=(ans*a[i].num)%MOD; } } else if(cnt==0)//全是正数 { for(int i=0;i<k;i++) ans=(ans*a[i].num)%MOD; } else { int nega=-1,posi=-1; cnt=0; for(int i=0;i<k;i++) { if(a[i].sign==-1) { //nega记录前K个中最后一个负数的下标 //cnt记录前k个中负数的个数,每满2个就乘一次 cnt++; if(nega==-1) nega=i; else { if((cnt&1)==0)//保持负数是一对的样子乘上去 { ans=(ans*a[nega].num)%MOD; ans=(ans*a[i].num)%MOD; } nega=i; } } else { //posi记录前k个中最后一个正数的下标 //每次只乘上前一个正数,留最后一个正数做交换 if(posi==-1) posi=i; else { ans=(ans*a[posi].num)%MOD; posi=i; } } } if((cnt&1)==0)//负数为偶数个,则直接取前k个数便可,把最后一个正数乘上便可 ans=(ans*a[posi].num)%MOD; else { int nega1=-1,posi1=-1; for(int i=k;i<n;i++) { if(a[i].sign==-1)//找绝对值最大的负数 { if(nega1==-1) nega1=i; } else//找最大的正数 { if(posi1==-1) posi1=i; } if(nega1!=-1&&posi1!=-1) break; } if(nega1!=-1&&posi1!=-1) { //比较是前k个中最后一个负数和后面绝对值最大的负数乘积大 //仍是前k个中最后一个正数和后面最大的正数乘积大 if(a[nega].num*a[nega1].num>a[posi].num*a[posi1].num) { ans=(ans*a[nega].num)%MOD; ans=(ans*a[nega1].num)%MOD; } else { ans=(ans*a[posi].num)%MOD; ans=(ans*a[posi1].num)%MOD; } } else if(posi1!=-1)//后面只有正数了 { ans=(ans*a[posi].num)%MOD; ans=(ans*a[posi1].num)%MOD; } else//后面只有负数了 { ans=(ans*a[nega].num)%MOD; ans=(ans*a[nega1].num)%MOD; } } } } cout<<ans<<endl; return 0; }
说明:因为是练手代码,全部题解源码未专门作优化处理,仅供参考,谢谢阅读!!!
感谢:3 ~ 9届蓝桥杯比赛原题点击传送