ZOJ How Many Nines 模拟 | 打表
How Many Nines
Time Limit: 1 Second Memory Limit: 65536 KB
If we represent a date in the format YYYY-MM-DD (for example, 2017-04-09), do you know how many 9s will appear in all the dates between Y1-M1-D1 and Y2-M2-D2 (both inclusive)?
Note that you should take leap years into consideration. A leap year is a year which can be divided by 400 or can be divided by 4 but can't be divided by 100.
Input
The first line of the input is an integer T (1 ≤ T ≤ 105), indicating the number of test cases. Then T test cases follow. For each test case:
The first and only line contains six integers Y1, M1, D1, Y2, M2, D2, their meanings are described above.
It's guaranteed that Y1-M1-D1 is not larger than Y2-M2-D2. Both Y1-M1-D1 and Y2-M2-D2 are between 2000-01-01 and 9999-12-31, and both dates are valid.
We kindly remind you that this problem contains large I/O file, so it's recommended to use a faster I/O method. For example, you can use scanf/printf instead of cin/cout in C++.
Output
For each test case, you should output one line containing one integer, indicating the answer of this test case.
Sample Input
4
2017 04 09 2017 05 09
2100 02 01 2100 03 01
9996 02 01 9996 03 01
2000 01 01 9999 12 31
Sample Output
4
2
93
1763534
Hint
For the first test case, four 9s appear in all the dates between 2017-04-09 and 2017-05-09. They are: 2017-04-09 (one 9), 2017-04-19 (one 9), 2017-04-29 (one 9), and 2017-05-09 (one 9).
For the second test case, as year 2100 is not a leap year, only two 9s appear in all the dates between 2100-02-01 and 2100-03-01. They are: 2017-02-09 (one 9) and 2017-02-19 (one 9).
For the third test case, at least three 9s appear in each date between 9996-02-01 and 9996-03-01. Also, there are three additional nines, namely 9996-02-09 (one 9), 9996-02-19 (one 9) and 9996-02-29 (one 9). So the answer is 3 × 30 + 3 = 93.
Submit Status
这题其实用一个数组int sum[10000][12][31]表示前缀和,第i年,第j个月,第k天有多少个合法情况。
然后区间减法即可。
不过我做的时候没想到这样,直接用模拟,wa良久。
我是先把begin的年份一直暴力向后算,算到新一年的1月1号,然后end的也一直向前算,算到那一年的1月一号。
然后直接对年份前缀和即可。然后边界很难处理。烦。。
如果能提交要再写一次。
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <assert.h>
#define IOS ios::sync_with_stdio(false)
using namespace std;
#define inf (0x3f3f3f3f)
typedef long long int LL; #include <iostream>
#include <sstream>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <string>
#include <bitset>
bool isyear(int val) {
if (val % == ) return true;
if (val % == && val % != ) return true;
return false;
}
int has[] = {, , , , , , , , , , , , };
void add(int &year, int &month, int &day) {
day++;
int t = has[month];
if (month == && isyear(year)) t++;
if (day > t) {
day = ;
month++;
if (month > ) {
year++;
month = ;
}
}
}
void cut(int &year, int &month, int &day) {
if (day != ) day--;
else {
if (month == ) {
month = ;
year--;
} else month--;
day = has[month];
if (month == && isyear(year)) day++;
}
}
bool toless(int year1, int month1, int day1, int year2, int month2, int day2) {
if (year1 < year2) return true;
if (month1 < month2) return true;
if (day1 < day2) return true;
return false;
}
int cnt(int val) {
int ans = ;
while (val / > ) {
ans += val % == ;
val /= ;
}
ans += val == ;
return ans;
}
LL sum[ + ];
void work() {
int year1, month1, day1;
int year2, month2, day2;
scanf("%d%d%d%d%d%d", &year1, &month1, &day1, &year2, &month2, &day2);
LL ans = ;
while (toless(year1, month1, day1, year2, month2, day2)) {
if (month1 == && day1 == ) {
break;
}
if (month1 == ) ans++;
if (day1 % == ) ans++;
ans += cnt(year1);
add(year1, month1, day1);
}
while (toless(year1, month1, day1, year2, month2, day2)) {
bool flag = false;
if (month2 == && day2 == ) {
flag = true;
}
if (month2 == ) ans++;
if (day2 % == ) ans++;
ans += cnt(year2);
if (flag) break;
cut(year2, month2, day2);
}
if (!(month1 == && day1 == )) { //样例一的情况,移动去不了1月1号
if (month1 == ) ans++;
if (day1 % == ) ans++;
ans += cnt(year1);
printf("%lld\n", ans);
return;
}
if (year1 == year2) { //1987 12 28 1988 1 1
ans += cnt(year1);
}
// cout << year1 << " " << month1 << " " << day1 << endl;
// cout << year2 << " " << month2 << " " << day2 << endl;
ans += sum[year2 - ] - sum[year1 - ];
printf("%lld\n", ans);
}
void init() {
int year = ;
while (year <= ) {
sum[year] += sum[year - ];
sum[year] += cnt(year) * ( + isyear(year));
sum[year] += ;
sum[year] += * ;
sum[year] += + isyear(year);
year++;
}
}
int main() {
#ifdef local
freopen("data.txt", "r", stdin);
// freopen("data.txt", "w", stdout);
#endif
init();
int t;
scanf("%d", &t);
while (t--) work();
return ;
}
其实一开始为什么不直接用sum[i][j][k]呢,是因为没想到,
以前比较日期大小,是直接i * 1000000 + j * 10000 + k * 10之类的hash,这样方便比较日期的大小,但是这样的下标就会非常大,需要hash,比较麻烦,所以就没用这个了。没想到用三维表示。其实hash也就是一个数组而已吧。
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <assert.h>
#define IOS ios::sync_with_stdio(false)
using namespace std;
#define inf (0x3f3f3f3f)
typedef long long int LL; #include <iostream>
#include <sstream>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <string>
#include <bitset>
bool isyear(int val) {
if (val % == ) return true;
if (val % == && val % != ) return true;
return false;
}
int has[] = {, , , , , , , , , , , , };
void cut(int &year, int &month, int &day) {
if (day != ) day--;
else {
if (month == ) {
month = ;
year--;
} else month--;
day = has[month];
if (month == && isyear(year)) day++;
}
}
int sum[ + ][][];
int cnt(int val) {
int ans = ;
while (val / > ) {
ans += val % == ;
val /= ;
}
ans += val == ;
return ans;
}
void init() {
for (int i = ; i <= ; ++i) {
for (int j = ; j <= ; ++j) {
for (int k = ; k <= has[j] + isyear(i); ++k) {
int preY = i, preM = j, preD = k;
cut(preY, preM, preD);
sum[i][j][k] = sum[preY][preM][preD];
sum[i][j][k] += cnt(i);
sum[i][j][k] += j == ;
sum[i][j][k] += k % == ;
}
}
}
}
void work() {
int beY, beM, beD, enY, enM, enD;
scanf("%d%d%d%d%d%d", &beY, &beM, &beD, &enY, &enM, &enD);
cut(beY, beM, beD);
printf("%d\n", sum[enY][enM][enD] - sum[beY][beM][beD]);
}
int main() {
#ifdef local
freopen("data.txt", "r", stdin);
// freopen("data.txt", "w", stdout);
#endif
init();
int t;
scanf("%d", &t);
while (t--) {
work();
}
return ;
}
code: 加个二分找pos,hash函数:i * 10000 + j * 100 + k
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <assert.h>
#define IOS ios::sync_with_stdio(false)
using namespace std;
#define inf (0x3f3f3f3f)
typedef long long int LL; #include <iostream>
#include <sstream>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <string>
#include <bitset>
bool isyear(int val) {
if (val % == ) return true;
if (val % == && val % != ) return true;
return false;
}
int has[] = {, , , , , , , , , , , , };
void cut(int &year, int &month, int &day) {
if (day != ) day--;
else {
if (month == ) {
month = ;
year--;
} else month--;
day = has[month];
if (month == && isyear(year)) day++;
}
}
int cnt(int val) {
int ans = ;
while (val / > ) {
ans += val % == ;
val /= ;
}
ans += val == ;
return ans;
}
int sum[ * * + ];
int tot[ * * + ], to;
int tohash(int a, int b, int c) {
return a * + b * + c;
}
void init() {
for (int i = ; i <= ; ++i) {
for (int j = ; j <= ; ++j) {
for (int k = ; k <= has[j] + (isyear(i) && j == ); ++k) {
tot[++to] = tohash(i, j, k);
sum[to] = sum[to - ];
sum[to] += cnt(i);
sum[to] += j == ;
sum[to] += k % == ;
}
}
}
}
void work() {
int beY, beM, beD, enY, enM, enD;
scanf("%d%d%d%d%d%d", &beY, &beM, &beD, &enY, &enM, &enD);
int res1 = tohash(beY, beM, beD);
int res2 = tohash(enY, enM, enD);
int posB = lower_bound(tot + , tot + + to, res1) - tot;
int posE = lower_bound(tot + , tot + + to, res2) - tot;
// cout << posB << " " << posE << endl;
printf("%d\n", sum[posE] - sum[posB - ]);
}
int main() {
#ifdef local
freopen("data.txt", "r", stdin);
// freopen("data.txt", "w", stdout);
#endif
init();
int t;
scanf("%d", &t);
while (t--) {
work();
}
return ;
}
ZOJ How Many Nines 模拟 | 打表的更多相关文章
- C# Excel 为图表添加模拟运算表
Excel中的图表能够将数据可视化,方便我们比较分析数据.但也有一定的局限,例如:不能够直接从图表中读出原来数据的准确值.Excel提供的解决方案是,在图表下方添加一个模拟运算表,即在坐标轴下方添加包 ...
- .Net模拟提交表单
2016-09-0210:49:20 以中邮速递API为服务接口,由于提交方式为表单提交,我要获取返回值来处理其他业务,所以一开始尝试采用Js后台获取返回值,但是涉及到跨域请求限制问题,那边服务端接口 ...
- 通过HttpURLConnection模拟post表单提交
通过HttpURLConnection模拟post表单提交 package junit; import java.io.InputStream; import java.net.HttpURLConn ...
- nodejs 模拟form表单上传文件
使用nodejs来模拟form表单进行文件上传,可以同时上传多个文件. 以前项目里有这个方法,最近在客户那里出问题了,同事说,这个方法从来就没管用过,SO,用了一天时间把这个方法给搞出来了(觉得花费的 ...
- js模拟form表单提交数据, js模拟a标签点击跳转,避开使用window.open引起来的浏览器阻止问题
js模拟form表单提交数据, js模拟a标签点击跳转,避开使用window.open引起来的浏览器阻止问题 js模拟form表单提交数据源码: /** * js模拟form表单提交 * @param ...
- js_ajax模拟form表单提交_多文件上传_支持单个删除
需求场景: 用一个input type="file"按钮上传多张图片,可多次上传,可单独删除,最后使用ajax模拟form表单提交功能提交到指定方法中: 问题:由于只有一个file ...
- 通过JS模拟select表单,达到美化效果[demo][转]
转自: http://www.cnblogs.com/dreamback/p/SelectorJS.html 通过JS模拟select表单,达到美化效果 Demo ------------------ ...
- HIT 2715 - Matrix3 - [最小费用最大流][数组模拟邻接表MCMF模板]
题目链接:http://acm.hit.edu.cn/hoj/problem/view?id=2715 Time limit : 5 sec Memory limit : 64 M Zhouguyue ...
- 通过JS模拟select表单,达到美化效果[demo]
.m-form{background:#fff;padding:50px;font-family:12px/1.5 arial,\5b8b\4f53,sans-serif;} .m-form ul,. ...
随机推荐
- hdu 1029 Ignatius and the Princess IV(排序)
题意:求出现次数>=(N+1)/2的数 思路:排序后,输出第(N+1)/2个数 #include<iostream> #include<stdio.h> #include ...
- spring mvc提交日期类型参数
如题,spring mvc直接提交Date类型参数会报错,400 bad request的错误.在controller里加上 @InitBinder protected void initBinder ...
- hdu 6053(To my boyfriend)
-----------题目链接------------- 题目描述: 给定一个矩阵,定义\(f(A)\) 为矩阵中不同元素的个数.现在要求\(f(A)\)的期望. 解法: 首先来暴力的,复杂度大约:\ ...
- (QACNN)自然语言处理:智能问答 IBM 保险QA QACNN 实现笔记
follow: https://github.com/white127/insuranceQA-cnn-lstm http://www.52nlp.cn/qa%E9%97%AE%E7%AD%94%E7 ...
- 数组(Array)的初始化
如果这样: private static int unsorted[]; for(int i = 1 ; i < 8 ; i ++ ) unsorted[i] = 1 ; 是会报NullPoin ...
- python+Django实现Nagios自动化添加监控项目
最近机房刚上了一批机器(有100台左右),需要使用Nagios对这一批机器进行监控.领导要求两天时间完成所有主机的监控.从原来的经验来看,两天时间肯定完成不了.那怎么办?按照之前的想法,肯定是在nag ...
- python print 字体颜色
例子: print '\033[35;43m(1)ip转换成数字\033[0m' \033[35;43m ===>35列属于字颜色,43列属于背景颜色 字背景颜色范围: 40--49 4 ...
- js 改变对象的引用地址
在业务处理中我们经常会碰到列表中有编辑和新增按钮,为了能够提高代码的公用性,我们经常会使用同一组件处理. 这样会出现一个问题就是编辑的时候直接把对象传过去,直接赋值,引用地址是同一个,所以不管修改了那 ...
- vue 常用的表单验证,包括手机号码,固定电话和身份证...
<template> <div> <pl-content-box> <pl-page-nav :show-previous=true></pl-p ...
- Makefile的常用技术总结
一.MAKE中的自动变量: $@: 表示target的名字 $%: 仅当目标是函数库文件中,表示规则中的目标成员名.例如,如果一个目标是"foo.a(bar.o)",那 ...