• NOIP复习模拟赛day2


    1. 又岂在

    (whether.pas/c/cpp)

    【问题描述】

    “ 我行过许多地方的桥,看过许多次数的云,喝过许多种类的酒,却只爱过一个正当最好年龄的人。”——沈从文

    W给小K买了一个最新款的机器模型。作为最新的机器模型,当然有了与以往不同的全新功能,那就是它能够自动行走!!!厉害吧(好吧,我自重)。新的机器模型可以按照K给出的命令来进行移动,命令包含“E”、“S”、“W”、“N”四种,分别对应了移动的四个不同的方向,分别为东、南、西、北。在机器模型执行某个命令时,它会向着对应方向移动一个单位。当然作为新型机器人,它不会只单单执行一个命令,它可以执行K给的命令串。对于给出的命令串,每一秒它会按照命令行动一次。而执行完该命令串的最后一个命令后,机器模型会自动从头开始循环。在0 时刻时K将机器模型放置在了(0,0)的位置,并且输入了命令串。K想要知道T 秒后机器模型所在的位置坐标。

    【输入】

    第一行读入一个字符串,表示K输入的命令串,保证至少有1 个命令。
    第二行读入一个正整数T。

    【输出】

    共一行,输出两个整数,表示T秒时,机器模型的坐标。

    【输入输出样例】

    NSWWNSNEEWN

    12

    -1 3

    【数据范围】

    对于60%的数据:T <= 500,000 且命令串长度<= 5,000
    对于100%的数据:T <= 2,000,000,000 且命令串长度<= 5,000

    【注意】

    向东移动,坐标改变改变为(X+1,Y);

    向南移动,坐标改变改变为(X,Y-1);

    向西移动,坐标改变改变为(X-1,Y);

    向北移动,坐标改变改变为(X,Y+1);

    官方题解:

      观察题目,很显然,这是一道十分简单的模拟。
      不过模拟太慢了,我们可以让它更快些。
      先跑一边循环,记录下它循环结束的位移,然后比较它的时间与循环所需时间,直接跳过所有循环,然后最后跑一遍残缺的循环,或者直接找到这个位移,直接加进答案就好了。
      是不是很简单啊?

      (是啊,很简单,但是要怎么跳过整个循环呢???

    自己bb的题解:

      怎么跳过循环呢???

      当然是取余运算啊!!!

      我可以求出整个命令串整合起来的命令(比如,整个命令串要求你向North or South and East or West 走几步)*((T-(T%strlen(s)))/strlen(s))     (s表示命令串的长度);

      然后在通过取余运算执行剩下的命令;

      好了,代码......

      

     1 #include<bits/stdc++.h>
     2 #define Re register int 
     3 using namespace std;
     4 long long T,Len,E,S,W,N,t,x,y;
     5 char s[5005];
     6 int main(){
     7     Re i,j;
     8     scanf("%s",s);scanf("%lld",&T);
     9     Len=strlen(s);
    10     if (T<=Len){
    11         for (i=0;i<Len;i++){
    12             if (s[i]=='E') E++;
    13             if (s[i]=='W') W--;
    14             if (s[i]=='N') N++;
    15             if (s[i]=='S') S--;    
    16         }
    17         printf("%lld %lld",E+W,N+S);
    18         return 0;
    19     }//其实第一个判断纯属无聊
    20     for (i=0;i<Len;i++){
    21         if (s[i]=='E') E++;
    22         if (s[i]=='W') W--;
    23         if (s[i]=='N') N++;
    24         if (s[i]=='S') S--;    
    25     }
    26     x=E+W;y=N+S; t=int(T/Len); x*=t; y*=t;
    27     E=W=N=S=0;
    28     for (i=0;i<T%Len;i++){
    29         if (s[i]=='E') E++;
    30         if (s[i]=='W') W--;
    31         if (s[i]=='N') N++;
    32         if (s[i]=='S') S--;
    33     }
    34     printf("%lld %lld",x+E+W,y+N+S);
    35     return 0;
    36 }
    View Code

      2.暮暮

      第二题太恐怖了这是什么鬼,硬生生的把数论转成了图论......

      给个链接吧:Alkri无敌

      给个代码吧......

      SPFA版本

      

     1 //NOIPRP++
     2 #include<bits/stdc++.h>
     3 #define Re register int
     4 using namespace std;
     5 int X,Y,Z,Num,head[100005],vis[100005];
     6 long long H,dis[100005],ans;
     7 queue<int> q;
     8 struct Edge{
     9     int To,Next,w;
    10 }edge[200005];
    11 inline void AddNum(int u,int v,int w){
    12     edge[++Num].Next=head[u];
    13     edge[Num].To=v;
    14     edge[Num].w=w;
    15     head[u]=Num;
    16 }
    17 int main(){
    18     Re i,j;
    19     scanf("%lld%d%d%d",&H,&X,&Y,&Z);
    20     for (i=0;i<X;i++) AddNum(i,(i+Y)%X,Y),AddNum(i,(i+Z)%X,Z);
    21     memset(dis,63,sizeof(dis)); memset(vis,false,sizeof(vis));
    22     dis[1%X]=1; vis[1%X]=true; q.push(1%X);
    23     while (!q.empty()){
    24         int Now=q.front(); q.pop(); vis[Now]=false;
    25         for (i=head[Now];i;i=edge[i].Next){
    26             int k=edge[i].To;
    27             if (dis[k]>dis[Now]+edge[i].w){
    28                 dis[k]=dis[Now]+edge[i].w;
    29                 if (!vis[k]){
    30                     vis[k]=true;
    31                     q.push(k);
    32                 }
    33             }
    34         }
    35     }
    36     for (i=0;i<X;i++) if (dis[i]<=H) ans+=(H-dis[i])/X+1;
    37     printf("%lld",ans);
    38     return 0;
    39 }
    40 //NOIPRP++
    View Code

      dijkstra版本,跑得比SPFA慢,玄学......

     1 //NOIPRP++
     2 #include<bits/stdc++.h>
     3 #define Re register int
     4 #define pa pair<int,int>
     5 using namespace std;
     6 int X,Y,Z,Num,head[100005],vis[100005];
     7 long long H,dis[100005],ans;
     8 priority_queue<pa , vector<pa> ,greater<pa> > q;
     9 struct Edge{
    10     int To,Next,w;
    11 }edge[200005];
    12 inline void AddNum(int u,int v,int w){
    13     edge[++Num].Next=head[u];
    14     edge[Num].To=v;
    15     edge[Num].w=w;
    16     head[u]=Num;
    17 }
    18 int main(){
    19     Re i,j;
    20     scanf("%lld%d%d%d",&H,&X,&Y,&Z);
    21     for (i=0;i<X;i++) AddNum(i,(i+Y)%X,Y),AddNum(i,(i+Z)%X,Z);
    22     memset(dis,63,sizeof(dis)); memset(vis,false,sizeof(vis));
    23     dis[1%X]=1; vis[1%X]=true; q.push(make_pair(dis[1%X],1%X));
    24     while (!q.empty()){
    25         int Now=q.top().second; q.pop(); vis[Now]=false;
    26         for (i=head[Now];i;i=edge[i].Next){
    27             int k=edge[i].To;
    28             if (dis[k]>dis[Now]+edge[i].w){
    29                 dis[k]=dis[Now]+edge[i].w;
    30                 if (!vis[k]){
    31                     vis[k]=true;
    32                     q.push(make_pair(dis[k],k));
    33                 }
    34             }
    35         }
    36     }
    37     for (i=0;i<X;i++) if (dis[i]<=H) ans+=(H-dis[i])/X+1;
    38     printf("%lld",ans);
    39     return 0;
    40 }
    41 //NOIPRP++
    View Code

      大佬打的版本,跑得最快......

     1 #include<cstdio>
     2 #define ll long long
     3 #include<cstring>
     4 ll n,ans,t[100050];
     5 int x,y,z;
     6 int main(){
     7     scanf("%lld%d%d%d",&n,&x,&y,&z);
     8     if (y>z)y^=z,z^=y,y^=z;
     9     if (x>y)x^=y,y^=x,x^=y;
    10     memset(t,-1,sizeof t);
    11     if (x==1)t[0]=1;else t[1]=1;
    12     for (int i=0;i<x;i++){
    13         int lt=(i-y%x+x)%x,p=i;
    14         while (t[lt]>0&&(t[lt]+y<t[p]||t[p]<0)){
    15             t[p]=t[lt]+y;
    16             lt=p;
    17             p=(p+y%x)%x;
    18         }
    19     }
    20     for (int i=0;i<x;i++){
    21         int lt=(i-z%x+x)%x,p=i;
    22         while (t[lt]>0&&(t[lt]+z<t[p]||t[p]<0)){
    23             t[p]=t[lt]+z;
    24             lt=p;
    25             p=(p+z%x)%x;
    26         }
    27     }
    28     for (int i=0;i<x;i++)if (t[i]>0&&t[i]<=n)ans+=(n-t[i])/x+1;
    29     printf("%lld
    ",ans);
    30 }
    View Code

     

  • 相关阅读:
    109. 有序链表转换二叉搜索树
    108. 将有序数组转换为二叉搜索树
    235. 二叉搜索树的最近公共祖先
    538. 把二叉搜索树转换为累加树
    230. 二叉搜索树中第K小的元素
    669. 修剪二叉搜索树
    513. 找树左下角的值
    637. 二叉树的层平均值
    671. 二叉树中第二小的节点
    DDL-Oracle中的5种约束总结(未完待续)
  • 原文地址:https://www.cnblogs.com/to-the-end/p/9906465.html
Copyright © 2020-2023  润新知