目录
1.第几天
2.明码
3.乘积尾零
4.测试次数
5.递增三元组
6.日志统计
7.乘积最大
1.第几天
题目解析:这题是不是和以前有点印象,就是日期类但是是日期的减法。
cpp
#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;
else
return 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点阵。
cpp
#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 << " ";
else
cout << "*";
}
t = m;
tmp = t.to_string();
len = tmp.size();
for(int i = 0; i < len; i++)
{
if(tmp[i] == '0')
cout << " ";
else
cout << "*";
}
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的对数。
cpp
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]就是答案。
cpp
#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数组的个数,然后将个数相乘就会得到排序的个数。
cpp
#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.日志统计
题目解析:这个题目就是依葫芦画瓢。看代码哦。
cpp
#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为奇数。再在这两种情况当中分负数的有全部,以及部分分为偶数个和奇数个,还有全部是正数的。这样就可以编写了。
cpp
#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。