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\n",ans);
30 }
View Code

 

 

 

posted @ 2018-11-04 22:58  to_the_end  阅读(248)  评论(0编辑  收藏  举报