目录
1.第几天
2.明码
3.乘积尾零
4.测试次数
5.递增三元组
6.日志统计
7.乘积最大
1.第几天
题目解析:这题是不是和以前有点印象,就是日期类但是是日期的减法。
#include <iostream>
using namespace std;class Date
{
public: Date(int year, int month, int day):_year(year),_month(month),_day(day){if(!(year >= 0 && month >= 0 && month < 13 && day > 0 && day < getmonthday(year,day)))cout << "非法日期" << endl;}int getmonthday(int year, int month){int Month[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};int day = Month[month];if(month == 2 && (year % 400 == 0) || (year % 4 == 0 && year % 100 != 0))day++;return day;}bool operator>(const Date& d)const{if(_year > d._year)return true;else if(_year == d._year && _month > d._month)return true;else if(_year == d._year && _month == d._month && _day > d._day)return true;elsereturn false;}bool operator==(const Date& d)const{return _year == d._year &&_month == d._month &&_day == d.day;}bool operator<(const Date& d)const{return !(*this = d);}bool operator>=(const Date& d)const{return *this > d || *this == d;}bool operator<=(const Date& d)const{return !(*this > d);}bool operator!=(const Date& d)const{return !(*this == d);}Date& operator+=(int day){if(day < 0)return *this -= -day;_day += day;while(_day > getmonthday(year, month)){day -= getmonthday(year, month);_month++;if(_month == 13){_month = 1;year++;}}return *this;}Date& operator+(int day) const{Date ret(*this);//拷贝构造ret += day;return ret;}Date& operator-=(int day) {if(day < 0)return *this += -day;_day = day;while(_day <= 0){_month--;if(_month == 0){_month = 12;_year--;}_day += getmonthday(_year, _month);}return *this;}Date operator-(int day) const{Date ret(*this);ret -= day;retuen ret;}Date& operator++(){*this += 1;return *this;}Date& operator++(int){Date& ret(*this);*this += 1;return ret;}Date& operator--(){*this -= 1;return *this;}Date& operator--(int){Date& ret(*this);*this -= 1;return ret;}int operator-(const Date& d) const[Date max = *this;Date min = d;int flag = 1;if(*this < d){max = d;min = *this;flag = -1;}int count = 0;while(min != max){++min;++count;}return count * flag;]private:int _year;int _month;int _day;
};int main()
{Date d1(2000, 1, 1);Date d2(2000, 5, 4);int count = d2 - d1;cout << count << endl;return 0;
}
2.明码
题目解析:看清题目,其实就是进制转换。再将数据是2个字节一起处理是16点阵。
#include <iostream>
#include<bitset>
#include<string>
using namespace std;int main()
{int n, m;int len;string tmp;//因为是16个点阵一个字节8个信息,那么一次就需要两个字节。while(cin >> n >> m){bitset<8> t;t = n;tmp = t.to_string();len = tmp.size();for(int i = 0; i < len; i++){if(tmp[i] == '0')cout << " ";elsecout << "*";}t = m;tmp = t.to_string();len = tmp.size();for(int i = 0; i < len; i++){if(tmp[i] == '0')cout << " ";elsecout << "*";}cout << endl;}return 0;
}
3.乘积尾零
题目解析:如果直接暴力那么绝对会超出范围,可以这么想。看下面的规律
2*5 = 10; 2*1*5*1 = 10 一个2一个5就是一个0
4*25 = 100 2*2*5*5=100
8*125 = 2*2*2*5*5*5 = 1000;
本质就会转化为求取2和5的对数。
int main()
{int num[10*10] ={ 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 count_2 = 0, count_5 = 0;for (int i = 0; i < sizeof(num) / sizeof(int); i++){int tmp = num[i];while (tmp % 2 == 0){count_2++;}while (tmp % 5 == 0){count_5++;}}cout << min(count_2,count_5) << endl;return 0;
}
4.测试次数
题目解析:本质是动态规划,dp[i][j]表示i个手机在j层的运气最坏的测试数。如果在第k层手机摔坏,那么就要到下一层进行测试一次,没摔坏就是要到上一层进行测试。状态转移方程就是dp[j][i] = min(dp[j][i],max(dp[j-1][k-1], dp[j][j-k])+1);最后返回dp[3][1000]就是答案。
#include <iostream>
#include<climits>
using namespace std;
//dp[i][j]表示i个手机在j层的运气最坏的测试数。
int dp[5][1007];int main()
{for(int i = 1; i <= 3;i++){for(int j = 1; j <= 1000; j++){dp[i][j] = j;}}//楼层数for(int i = 1; i <= 1000; i++){//手机数for(int j = 2; j <= 3; j++){//从摔坏楼层开始走。for(int k = 1; k < i; k++){dp[j][i] = min(dp[j][i], max(dp[j-1][k-1], dp[j][i - k]) + 1);}}}cout << dp[3][1000] << endl;return 0;
}
5.递增三元组
题目解析:先将数组进行排序,使得它们变得有序,然后就是利用两个指针进行将a,c数组找到第一个小于b数组的个数,然后将个数相乘就会得到排序的个数。
#include <iostream>
#include<algorithm>
using namespace std;#define N 100010
int n;
int a[N], b[N], c[N];
long long ret = 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];}for(int i = 1; i <= n; i++){cin >> c[i];}//排序;sort(a + 1, a + n + 1);sort(b + 1, b + n + 1); sort(c + 1, c + n + 1);int j = 1;int k = 1;for(int i = 1; i <= n; i++){while(j <= n && a[j] < b[i]) j++;//找到第一个数组种第一次大于第二个数组的数;while(k <= n && c[k] <= b[i]) k++;//找到第三个数组种第一次大于第二个数组的数;ret += (long long) (j - 1) * (n - k + 1);}cout << ret << endl;return 0;
}
6.日志统计
题目解析:这个题目就是依葫芦画瓢。看代码哦。
#include <iostream>
#include<vector>
#include<algorithm>
#include<map>
#include<set>
using namespace std;int N, D, K;struct log
{int id, ts;
};bool cmp(log a, log b)
{return a.ts < b.ts;
}int main()
{cin >> N >> D >> K;vector<log> logs(N);for(int i = 0; i < N; i++){cin >> logs[i].ts >> logs[i].id;}sort(logs.begin(), logs.end(), cmp);//记录答案set<int> ans;//id出现次数map<int, int> cnt;int j = 0;for(int i = 0; i < N; i++){//时间间隔不大于D.while(j < N && logs[j].ts - logs[i].ts < D){cnt[logs[j].id]++;//出现次数++//并且id数>=k,就记录一下答案。if(cnt[logs[j].id] >= K) ans.insert(logs[j].id);j++;}cnt[logs[i].id]--;} for(set<int>::iterator i = ans.begin(); i != ans.end(); i++)cout << *i << endl;return 0;
}
7.乘积最大
题目解析:本题目就是分类讨论,首先将数组元素进行排序,可以分为三种情况,第一就是全选k == n; 那么就直接选择相乘,然后就是其中进行挑选。k < n;也分两种;一种挑选的k为偶数,一种挑选k为奇数。再在这两种情况当中分负数的有全部,以及部分分为偶数个和奇数个,还有全部是正数的。这样就可以编写了。
#include <iostream>
#include<algorithm>
using namespace std;
#define MOD 1000000009;const int N = 100010;
long long int a[N];
int main()
{int n, k;cin >> n >> k;int flag = 0;//统计负数for(int i = 0; i < n; i++){cin >> a[i];if(a[i] < 0)flag++;}sort(a, a + n);long long int ans = 1;//记录乘积答案//全部是负数并且k为奇数if(k % 2 != 0 && flag == n){for(int i = 0; i < k; i++){ans = ans * a[n - 1 - i] % MOD;ans = ans % MOD;}cout << ans << endl;return 0;}//奇数选择】最大的先;if(k % 2 != 0){ans = a[n - 1];n--;k--;}int t = 0;int left = 0, right = n - 1;//左右两边进行选择;while(t < k){if(a[left] * a[left + 1] >= a[right] * a[right - 1]){long long tmp = a[left] * a[left + 1] % MOD;ans = ans * tmp % MOD;ans = ans % MOD;left += 2;t += 2;}else{long long tmp = a[right] * a[right - 1] % MOD;ans = ans * tmp % MOD;ans = ans % MOD;right -= 2;t += 2;}}cout << ans << endl;return 0;
}
蓝桥杯冲冲冲,加油xdm。