原题链接
题意很容易理解,给你处于同一天的两个时间,如果第一个时间比第二个时间早,输出YES
,否则输出NO
。
C o d e Code Code
#include
int main() {
int h1, m1, s1;
int h2, m2, s2;
// 阿七发视频的时间
scanf("%d%d%d", &h1, &m1, &s1);
// 小赖狗发视频的时间
scanf("%d%d%d", &h2, &m2, &s2);
int time1 = h1 * 3600 + m1 * 60 + s1;
int time2 = h2 * 3600 + m2 * 60 + s2;
// 如果小赖狗发视频的时间 time2 比阿七发视频的时间 time1 晚
// 那么能在小赖狗视频中看见阿七的视频
if (time2 > time1) {
puts("YES");
} else {
puts("NO");
}
return 0;
}
计算第 a a a 页到第 b
页之间所有页码对应的数字的长度的和即可,可以直接无脑枚举所有情况。
#include
int a, b;
int cnt; // 蒙面人出的题的答案
int cnt_mxt; // mxt算出的答案
int main() {
scanf("%d%d%d", &a, &b, &cnt_mxt);
for (int i = a; i <= b; i ++) {
if (i <= 9) { // 数字1~9中,每个数字的长度都是1
cnt ++;
} else if (i <= 99) { // 数字10~99中,每个数字的长度都是2
cnt += 2;
} else if (i <= 999) { // 数字100~999中,每个数字的长度都是3
cnt += 3;
} else if (i <= 9999) { // 数字1000~9999中,每个数字的长度都是4
cnt += 4;
} else if (i <= 99999) { // 数字10000~99999中,每个数字的长度都是5
cnt += 5;
} else if (i <= 999999) { // 数字100000~999999中,每个数字的长度都是6
cnt += 6;
} else if (i <= 9999999) { // 数字1000000~9999999中,每个数字的长度都是7
cnt += 7;
} else { // 数字10000000~99999999中,每个数字的长度都是8
cnt += 8;
}
}
// 如果两个答案一致,那么mxt就做对了
if (cnt == cnt_mxt) {
puts("nizhenlihai!");
} else {
puts("laji");
}
return 0;
}
虽然这个题很简单,但其实改编自一道经典的数位统计DP
,原题目如下:
给你两个整数 a a a 和 b b b,求 a a a 和 b b b 之间所有数字中 0 0 0 ~ 9 9 9 各自的出现次数。
例如, a = 1024 a = 1024 a=1024, b = 1032 b = 1032 b=1032,则 a a a 和 b b b 之间共有 9 9 9 个数如下:
1024 1025 1026 1027 1028 1029 1030 1031 1032
其中 0
出现 10 10 10 次,1
出现 10 10 10 次,2
出现 7 7 7 次,3
出现 3 3 3 次等等…
输入包含多组测试数据。
每组测试数据占一行,包含两个整数 a a a 和 b b b。其中 0 < a , b < 100000000 0~<~a,b~<~100000000 0 < a,b < 100000000。
当读入一行为 0 0
时,表示输入终止,且该行不作处理。
每组数据输出一个结果,每个结果占一行。
每个结果包含十个用空格隔开的数字,第一个数字表示 0
出现的次数,第二个数字表示 1
出现的次数,以此类推。
C o d e Code Code
#include
int count(int n, int i) { // 1 ~ n 中数字 i 出现的次数
int sum = 0;
// 循环中每一次sum都加上满足0 <= xxxiyyy <= abcdefg的xxxiyyy的个数
for (int base = 1; base <= n; base *= 10) {
// 1 xxx <= abc - 1
sum += (n / (base * 10) - (i == 0)) * base;
// 2 xxx == abc
if (n / base % 10 > i) // 2.1 d > i
sum += base;
if (n / base % 10 == i) // 2.2 d == i
sum += n % base + 1;
}
return sum;
}
int main() {
int a, b;
while (scanf("%d%d", &a, &b), a || b) {
if (a < b) {
int t = a; a = b; b = t;
}
for (int i = 0; i <= 9; i ++) {
printf("%d ", count(a, i) - count(b - 1, i));
}
puts("");
}
return 0;
}
题意:
给你两个由小写字母组成的字符串 s , t s, t s,t, 它们的长度相等。规定 s s s 和 t t t 的“差异度”为它们具有不同字符的位置数。你可以交换 s s s 中的两个字符(不交换也可以),使得 s s s 和 t t t 的“差异度”最小,并输出这个最小值。
思路:
我们最多可以交换依次 s s s 中的两个字符。很明显,交换一次字符会对二者的差异度产生以下影响:
计算好初始状态 s s s 与 t t t 的差异度后,我们先判断是否存在情况1
,因为这种情况可以使差异度减小 2 2 2,如果不存在 情况1
,我们再判断是否存在 情况2
。情况3
无需判断,因为它不能改变差异度。
判断 情况1
的存在性
假设交换了 s i , s j s_i,s_j si,sj ( i < j i < j i<j)使得差异度减小了 2 2 2,那么很容易知道交换前 s , t s,t s,t 满足: s i ! = t i s_i~!=~t_i si != ti, s j ! = t j s_j~!=~t_j sj != tj, s i = t j s_i~=~t_j si = tj, s j = t i s_j~=~t_i sj = ti。
我们可以选择遍历 s s s ,如果 s j ! = t j s_j~!=~t_j sj != tj,我们判断之前遍历过程中有没有遇见一个下标 i i i,满足 s i = t j s_i~=~t_j si = tj 且 s j = t i s_j~=t_i~ sj =ti 。
判断 情况2
的存在性
与 情况1
类似,假设交换了 s i , s j s_i,s_j si,sj ( i < j i < j i<j)使得差异度减小了 1 1 1,那么存在以下两种情况(在 s i ! = t i s_i~!=~t_i si != ti, s j ! = t j s_j~!=~t_j sj != tj 条件下):
C o d e Code Code
#include
int n;
char s[200010];
char t[200010];
int main() {
scanf("%d", &n);
scanf("%s%s", s + 1, t + 1);
// res:s没有交换字符时两个字符串的“差异度”
int res = 0;
for (int i = 1; i <= n; i ++) {
if (s[i] != t[i]) {
res ++;
}
}
// 情况1,判断是否存在一种交换方式,使得res减小2
int exist[27][27] = {0};
for (int i = 1; i <= n; i ++) {
if (s[i] != t[i]) {
int pos_s = s[i] - 'a' + 1;
int pos_t = t[i] - 'a' + 1;
if (exist[pos_t][pos_s]) {
printf("%d\n", res - 2);
return 0;
}
// 因为s[i]!=t[i],所以标记此时s[i]与t[i]的组合
exist[pos_s][pos_t] = i;
}
}
// 情况2,判断是否存在一种交换方式,使得res减小1
int exist1[27] = {0};
int exist2[27] = {0};
for (int i = 1; i <= n; i ++) {
if (s[i] != t[i]) {
int pos_s = s[i] - 'a' + 1;
int pos_t = t[i] - 'a' + 1;
if (exist1[pos_s]) { // 情况2.1
printf("%d\n", res - 1);
return 0;
}
if (exist2[pos_t]) { // 情况2.2
printf("%d\n", res - 1);
return 0;
}
exist1[pos_t] = i;
exist2[pos_s] = i;
}
}
printf("%d\n", res); // 情况1和情况2都不存在
return 0;
}