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 }
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++
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++
大佬打的版本,跑得最快......
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 }