[Offer收割]编程练习赛9,10

题目1 : 闰秒

时间限制:10000ms

单点时限:1000ms

内存限制:256MB

描述

计算机系统中使用的UTC时间基于原子钟,这种计时方式同“地球自转一周是24小时”的计时方式有微小的偏差。为了弥补这种偏差,我们偶尔需要增加一个“闰秒”。

最近的一次闰秒增加发生在UTC时间2016年的最后一天。我们在2016年12月31日23时59分59秒和2017年1月1日0时0分0秒之间增加了这样一秒:2016年12月31日23时59分60秒,记作2016-12-31 23:59:60。

目前一共增加了27次闰秒,具体添加的时间见下表:

给出两个时间,请你判断在考虑闰秒的情况下,这两个时间间隔多少秒。

输入

两个时间各占一行,格式是yyyy-MM-dd HH:mm:ss,范围在1970-01-01 00:00:00至2017-03-12 23:59:59之间。保证第一个时间不晚于第二个时间。

输出

两个时间间隔多少秒。

样例输入
2016-12-31 23:59:59
2017-01-01 00:00:00
样例输出
2

暴力模拟就好了,用ans[2]-ans[1]。

#include <stdio.h>
#include <cstring>
#include <cmath>
using namespace std;
typedef long long ll;
ll ans[5];
int Y[15]= {0,31,28,31,30,31,30,31,31,30,31,30,31}; //nor
char c[3][3][33]; // 0 y-m-d  1 h-mi-s
int y[5],m[5],d[5],h[5],mi[5],s[5];
int data[3000][5];
bool runnian(int a)
{
    if((a%4==0&&a%100!=0)||a%400==0) return 1;
    else return 0;
}
void debug()
{
    printf("%d %d %d**\n",y[1],m[1],d[1]);
    printf("%d %d %d\n",h[1],mi[1],s[1]);
    printf("%d %d %d\n",y[2],m[2],d[2]);
    printf("%d %d %d\n",h[2],mi[2],s[2]);
}
void init()
{
    memset(ans,0,sizeof(ans));
    memset(y,0,sizeof(y));
    memset(m,0,sizeof(m));
    memset(d,0,sizeof(d));
    memset(h,0,sizeof(h));
    memset(mi,0,sizeof(mi));
    memset(s,0,sizeof(s));
    data[1972][1]=1;
    data[1972][2]=1;
    for(int i=1973; i<=1979; i++) data[i][2]=1;
    for(int i=1981; i<=1983; i++) data[i][1]=1;
    data[1985][1]=1;
    data[1987][2]=1;
    data[1989][2]=1;
    data[1990][2]=1;
    for(int i=1992; i<=1994; i++) data[i][1]=1;
    data[1995][2]=1;
    data[1997][1]=1;
    data[1998][2]=1;
    data[2005][2]=1;
    data[2008][2]=1;
    data[2012][1]=1;
    data[2015][1]=1;
    data[2016][2]=1;
}

ll ansy=365*24*3600;
ll calnian(int y)
{
    ll ans=0;
    for(int i=1970; i<=y; i++) //年
    {
        ans+=ansy;
        if(runnian(i)) ans+=24*60*60;
        if(data[i][1]) ans++;
        if(data[i][2]) ans++;
    }
    return ans;
}

ll calyue(int y,int m)
{
    ll ans=0;
    for(int j=1; j<=m; j++) //月
    {
        ans+=Y[j]*24*60*60;
        if(j==2&&runnian(y)) ans+=24*60*60; //闰年2月+一天
        if(j==6&&data[y][1]) ans++;//闰秒也要
        if(j==12&&data[y][2]) ans++;
    }
    return ans;
}

ll calday(int y,int m,int d)
{
    int f=0;
    ll ans=0;
    if(runnian(y)&&m==2) ans+=24*3600;
    ans+=d*24*3600;
    if(m==6&&data[y][1]) ans++;
    return ans;
}

int main()
{
    init();
    for(int i=1; i<=2; i++)
        scanf("%d-%d-%d %d:%d:%d",&y[i],&m[i],&d[i],&h[i],&mi[i],&s[i]);
        //debug();
    for(int x=1; x<=2; x++)
    {
        ans[x]+=calnian(y[x]-1);
        ans[x]+=calyue(y[x],m[x]-1);
        ans[x]+=calday(y[x],m[x],d[x]-1);
        ans[x]+=h[x]*3600;
        ans[x]+=mi[x]*60;
        ans[x]+=s[x];
    }
    printf("%lld\n",ans[2]-ans[1]);
    return 0;
}

题目2 : 水陆距离

时间限制:10000ms

单点时限:1000ms

内存限制:256MB

描述

给定一个N x M的01矩阵,其中1表示陆地,0表示水域。对于每一个位置,求出它距离最近的水域的距离是多少。

矩阵中每个位置与它上下左右相邻的格子距离为1。

输入

第一行包含两个整数,N和M。

以下N行每行M个0或者1,代表地图。

数据保证至少有1块水域。

对于30%的数据,1 <= N, M <= 100

对于100%的数据,1 <= N, M <= 800

输出

输出N行,每行M个空格分隔的整数。每个整数表示该位置距离最近的水域的距离。

样例输入
4 4
0110
1111
1111
0110
样例输出
0 1 1 0
1 2 2 1
1 2 2 1
0 1 1 0

宽搜,只搜终点,搜过的点再加到队列里。

#include <queue>
#include <vector>
#include <stdio.h>
#include <iostream>
#include <string.h>
#include <stdlib.h>
#include <algorithm>
using namespace std;
const int inf=0x3f3f3f3f;
const int maxn=810;
int n,m;
int dir[4][2]={{0,1},{0,-1},{1,0},{-1,0}};
int vis[maxn][maxn];
char str[maxn][maxn];
int ans[maxn][maxn];
struct point{
    int x,y;
}sna[maxn*maxn];
struct edge{
    int x,y,step;
};
queue<edge>que;
void bfs(){
    edge c,ne;
    while(!que.empty()){
        c=que.front();que.pop();
        for(int i=0;i<4;i++){
            int xx=c.x+dir[i][0];
            int yy=c.y+dir[i][1];
            if(xx<0||xx>n-1||yy<0||yy>m-1||vis[xx][yy]==1) continue;
//            ans[xx][yy]=c.step+1;
            ans[xx][yy]=c.step+1;
            ne.x=xx;ne.y=yy;ne.step=c.step+1;
            vis[ne.x][ne.y]=1;
            que.push(ne);
        }
    }
}
int main(){
    while(scanf("%d%d",&n,&m)!=-1){
        while(!que.empty()) que.pop();
        memset(vis,0,sizeof(vis));
        for(int i=0;i<n;i++) scanf("%s",str[i]);
        for(int i=0;i<n;i++) for(int j=0;j<m;j++) ans[i][j]=inf;
        for(int i=0;i<n;i++){
            for(int j=0;j<m;j++){
                if(str[i][j]==‘0‘){
                    ans[i][j]=0;vis[i][j]=1;
                    edge c;
                    c.x=i;c.y=j;c.step=0;
                    que.push(c);
                }
            }
        }
        bfs();
//        for(int i=0;i<n;i++) for(int j=0;j<m;j++) ans[i][j]=min(ans[i][j],st[i][j]);
        for(int i=0;i<n;i++){
            for(int j=0;j<m;j++){
                if(j==m-1) printf("%d\n",ans[i][j]);
                else printf("%d ",ans[i][j]);
            }
        }
    }
    return 0;
}

题目2 : 出勤记录II

时间限制:10000ms

单点时限:1000ms

内存限制:256MB

描述

小Hi的算法课老师每次上课都会统计小Hi的出勤记录。迟到会被记录一个L,缺席会被记录一个A,按时上课会被记录一个O。

一学期结束,小Hi的出勤记录可以看成是一个只包含LAO的字符串,例如"OOOOLOOOLALLO……"。

如果小Hi整学期缺席不超过1次,并且没有连续3次迟到,小Hi的出勤记录就算合格。

现在给出字符串的长度N,小Hi想知道长度为N的出勤记录中,合格的记录总共有多少种。

例如长度为3的合格出勤记录有19种:OOO OOL OOA OLO OAO LOO AOO OLL OLA OAL LOL LOA AOL LLO LAO ALO LLA LAL ALL。

输入

一个整数N(1 <= N <= 100000)。

输出

长度为N的合格记录总数。由于结果可能很大,你只需输出结果模109+7的余数。

样例输入
3
样例输出
19

DP,一共6种状态。

012代表有A,0代表以A或O结尾,1代表以L结尾,2代表以LL结尾。

345代表无A,3代表以O结尾,4代表以L结尾,5代表以LL结尾。

而6代表总数。

转移一下就好了,转移方程见代码。

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
const ll mod=1e9+7;
ll dp[100005][10];
int main()
{
    int n;
    memset(dp,0,sizeof(dp));
    dp[1][6]=3;
    dp[2][0]=3;dp[2][1]=dp[2][4]=dp[2][5]=1;
    dp[2][3]=2;dp[2][2]=0;dp[2][6]=8;
    for(int i=3;i<=100000;i++)
    {
        dp[i][0]=(dp[i-1][0]+dp[i-1][1]+dp[i-1][2]+
        dp[i-1][3]+dp[i-1][4]+dp[i-1][5])%mod;
        dp[i][1]=dp[i-1][0]%mod;
        dp[i][2]=dp[i-1][1]%mod;
        dp[i][3]=(dp[i-1][3]+dp[i-1][4]+dp[i-1][5])%mod;
        dp[i][4]=dp[i-1][3]%mod;
        dp[i][5]=dp[i-1][4]%mod;
        dp[i][6]=(dp[i][0]+dp[i][1]+dp[i][2]+
        dp[i][3]+dp[i][4]+dp[i][5])%mod;
    }
    while(scanf("%d",&n)!=EOF)
    printf("%lld\n",dp[n][6]);
    return 0;
}
时间: 2024-09-30 10:50:51

[Offer收割]编程练习赛9,10的相关文章

hihocoder - [Offer收割]编程练习赛17

hihocoder - [Offer收割]编程练习赛17 题目1 : F1 Score 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 小Hi和他的小伙伴们一起写了很多代码.时间一久有些代码究竟是不是自己写的,小Hi也分辨不出来了. 于是他实现了一个分类算法,希望用机器学习实现自动分类. 为了评价这个分类算法的优劣,他选出了N份有标记的代码作测试集,并决定用F1 Score作为评价标准. 给出N份代码的实际作者是不是小Hi以及分类算法预测的结果,请你计算F1 Sco

HihoCoder1670 : 比赛日程安排([Offer收割]编程练习赛41)(模拟)

描述 H国编程联赛中有N只队伍,编号1~N. 他们计划在2018年一共进行M场一(队)对一(队)的比赛. 为了让参赛队员能得到充分的休息,联赛组委会决定:每支队伍连续两场比赛之间至少间隔一天.也就是如果A队1月1日参加了一场比赛,那么下一场比赛最早安排在1月3日. 给定M场比赛的时间和参赛的两支队伍,请你判断这个日程安排是否可行. 输入 第一行包含一个整数T,代表测试数据组数.(1 ≤ T ≤ 10) 对于每组数据,第一行包含两个整数N和M.(1 ≤ N ≤ 50, 1 ≤ M ≤ 1000)

[Offer收割]编程练习赛15 A.偶像的条件[贪心]

#1514 : 偶像的条件 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 小Hi的学校正面临着废校的大危机.面对学校的危机,小Hi同学们决定从ABC三个班中各挑出一名同学成为偶像. 成为偶像团体的条件之一,就是3名团员之间的身高差越小越好. 已知ABC三个班同学的身高分别是A1..AN, B1..BM 和 C1..CL.请你从中选出3名同学Ai, Bj, Ck使得D=|Ai-Bj|+|Bj-Ck|+|Ck-Ai|最小. 输入 第一行包含3个整数,N, M和L. 第

hihocoder [Offer收割]编程练习赛14 剑刃风暴

题目4 : 剑刃风暴 时间限制:20000ms 单点时限:2000ms 内存限制:256MB 描述 主宰尤涅若拥有一招非常厉害的招式——剑刃风暴,“无论是战士还是法师,都害怕尤涅若的武士刀剑技”. 现在战场上有N名敌对英雄,他们的位置分别为(Xi, Yi),而剑刃风暴的伤害范围是一个半径为R的圆形,尤涅若可以选择一个坐标作为剑刃风暴的中心,所有处于这个圆形范围内的英雄都会受到剑刃风暴的伤害. 现在尤涅若想要知道,他的剑刃风暴最多可以同时伤害到多少敌对英雄. 输入 第一行为两个整数N和R,分别敌对

[Offer收割]编程练习赛15 B.分数调查[加权并查集]

#1515 : 分数调查 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 小Hi的学校总共有N名学生,编号1-N.学校刚刚进行了一场全校的古诗文水平测验. 学校没有公布测验的成绩,所以小Hi只能得到一些小道消息,例如X号同学的分数比Y号同学的分数高S分. 小Hi想知道利用这些消息,能不能判断出某两位同学之间的分数高低? 输入 第一行包含三个整数N, M和Q.N表示学生总数,M表示小Hi知道消息的总数,Q表示小Hi想询问的数量. 以下M行每行三个整数,X, Y和S.表

[Offer收割]编程练习赛13 B.最大子矩阵[枚举]

#1502 : 最大子矩阵 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 给定一个NxM的矩阵A和一个整数K,小Hi希望你能求出其中最大(元素数目最多)的子矩阵,并且该子矩阵中所有元素的和不超过K. 输入 第一行包含三个整数N.M和K. 以下N行每行包含M个整数,表示A. 对于40%的数据,1 <= N, M <= 10 对于100%的数据,1 <= N, M <= 250 1 <= K <= 2147483647 1 <= Aij

hihocoder offer收割编程练习赛13 D 骑士游历

思路: 矩阵快速幂. 实现: 1 #include <iostream> 2 #include <cstdio> 3 #include <vector> 4 using namespace std; 5 6 typedef long long ll; 7 typedef vector<ll> vec; 8 typedef vector<vec> mat; 9 10 const ll mod = 1e9 + 7; 11 12 ll n, x, y;

hihocoder [Offer收割]编程练习赛4

描述 最近天气炎热,小Ho天天宅在家里叫外卖.他常吃的一家餐馆一共有N道菜品,价格分别是A1, A2, ... AN元.并且如果消费总计满X元,还能享受优惠.小Ho是一个不薅羊毛不舒服斯基的人,他希望选择若干道不同的菜品,使得总价在不低于X元的同时尽量低. 你能算出这一餐小Ho最少消费多少元吗? 输入 第一行包含两个整数N和X,(1 <= N <= 20, 1 <= X <= 100) 第二行包含N个整数A1, A2, ..., AN.(1 <= Ai <= 100)

[Offer收割]编程练习赛12 题目4 : 寻找最大值

时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 给定N个数A1, A2, A3, ... AN,小Ho想从中找到两个数Ai和Aj(i ≠ j)使得乘积Ai × Aj × (Ai AND Aj)最大.其中AND是按位与操作. 小Ho当然知道怎么做.现在他想把这个问题交给你. 输入 第一行一个数T,表示数据组数.(1 <= T <= 10) 对于每一组数据: 第一行一个整数N(1<=N<=100,000) 第二行N个整数A1, A2, A3, ... AN