Mike has a frog and a flower. His frog is named Xaniar and his flower is named Abol. Initially(at time 0), height of Xaniar is h1 and
height of Abol is h2.
Each second, Mike waters Abol and Xaniar.
So, if height of Xaniar is h1 and
height of Abol is h2,
after one second height of Xaniar will become and
height of Abol will become where x1,?y1,?x2 and y2 are
some integer numbers and denotes
the remainder of amodulo b.
Mike is a competitive programmer fan. He wants to know the minimum time it takes until height of Xania is a1 and
height of Abol is a2.
Mike has asked you for your help. Calculate the minimum time or say it will never happen.
Input
The first line of input contains integer m (2?≤?m?≤?106).
The second line of input contains integers h1 and a1 (0?≤?h1,?a1?<?m).
The third line of input contains integers x1 and y1 (0?≤?x1,?y1?<?m).
The fourth line of input contains integers h2 and a2 (0?≤?h2,?a2?<?m).
The fifth line of input contains integers x2 and y2 (0?≤?x2,?y2?<?m).
It is guaranteed that h1?≠?a1 and h2?≠?a2.
Output
Print the minimum number of seconds until Xaniar reaches height a1 and
Abol reaches height a2 or
print -1 otherwise.
Sample test(s)
input
5 4 2 1 1 0 1 2 3
output
3
input
1023 1 2 1 0 1 2 1 1
output
-1
Note
In the first sample, heights sequences are following:
Xaniar:
Abol:0 -> 3 -> 4 -> 1
这道题的思路一开始我看了一下题想到的是快速幂,然后加上打表然后求出循环节之类的,但是还是感觉无从下手。
后来学习了q神的那种暴力求法,也算是受益匪浅吧。
它的想法是:
首先我们先得找出h1与h2的循环周期,所以我们首先循环2*m遍,因为比如说首先有第一次到达了a1,那么肯定会有第二次到达a1,从而我们就可以求出循环节了。
首先肯定要mod,那么我终于搞懂了之前的一个理论,就是,一开始我不知道为什么在里面mod也是可以的,后来知道有公式a%b=a%b%b,所以这个是成立的。
我们把每次h1==a1或h2==a2时候的情况分别存到一个数组中去,然后就可以求周期了。但是如果两个数组为空的话那么就说明肯定是不可以的。
主函数中的那个for是暴力的关键,因为我们不知道要for几次,所以假设for很大的次数遍,然后具体的解释就已经写在代码中了,不理解的话可以看一下代码理解加思考下。
#include<stdio.h> #include<string.h> #include<iostream> #include<algorithm> #include<vector> using namespace std; #define maxn 1111111 typedef long long ll; vector<int>res1; vector<int>res2; __int64 m; int main(){ __int64 h1,a1,x1,y1,h2,a2,x2,y2; scanf("%I64d",&m); scanf("%I64d%I64d",&h1,&a1); scanf("%I64d%I64d",&x1,&y1); scanf("%I64d%I64d",&h2,&a2); scanf("%I64d%I64d",&x2,&y2); __int64 temp=2*m; for(int i=0;i<=temp;i++){ if(h1==a1){ res1.push_back(i); } if(h2==a2) res2.push_back(i); h1=(x1*h1%m+y1)%m; h2=(x2*h2%m+y2)%m; } if(res1.empty()||res2.empty()){ printf("-1\n"); return 0; } //这里的思路要理清楚; //首先t11中保存的是最先遇到a1的时间,然后t21中保存的是最先遇到a2的时间; //add1,2中保存的是两个的周期(循环节) __int64 t11=res1[0],t21=res2[0]; //我们假设时间是从t11和t21开始的,然后再在下面那个循环中进行操作 //当那个小的时候就加上那个的周期,然后判断是否两个时间会有可能相等。 __int64 tt=5*m; __int64 add1=res1[1]-res1[0],add2=res2[1]-res2[0]; for(int i=1;i<=tt;i++){ if(t11==t21){ printf("%I64d\n",t11); //注意__int64不要写错,要不然输出也是错误的; return 0; } if(t11<t21) t11+=add1; else if(t11>t21) t21+=add2; } printf("-1\n"); }
不过也真是暴力啊,但是也跑的很快,不错的想法!
然后稍微纪念一下我不小心挂掉的B题,我忘记了还有q个询问,然后就跑了三个for来找最小值,结果就T了。
B题的题意大致是每次让你求出n行中连续1的最大个数,也就是说每次先对每一行求连续1的最大个数,然后与其他的进行比较,最后再求一个最大值。但是这里我们不能每次都去for一遍每一行,因为这样太费时了,所以我们保存下来没有被改变过的行,然后把它与其他行进行比较,然后找出最大值,这也是一个好的想法。
#include<stdio.h> #include<string.h> #include<algorithm> using namespace std; #define maxn 555 int a[maxn][maxn]; int mm[maxn]; int main(){ int n,m,q; scanf("%d%d%d",&n,&m,&q); for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) scanf("%d",&a[i][j]); int nn=0,tot=0; for(int i=1;i<=n;i++){ nn=0; tot=0; for(int j=1;j<=m;j++){ nn=0; if(a[i][j]==1) nn++; else continue; for(int k=j+1;k<=m;k++){ if(a[i][k]==a[i][k-1]&&a[i][k]==1) nn++; else break; } tot=max(nn,tot); } mm[i]=tot; } #if 1 while(q--){ int x,y; scanf("%d%d",&x,&y); int num=0; if(a[x][y]==1) a[x][y]=0; else if(a[x][y]==0) a[x][y]=1; for(int i=1;i<=m;i++){ int tt=0; if(a[x][i]==1) tt++; else continue; for(int j=i+1;j<=m;j++){ if(a[x][j]==a[x][j-1]&&a[x][j]==1) tt++; else break; } num=max(num,tt); } mm[x]=num; int q=-1; for(int i=1;i<=n;i++){ if(q<mm[i]) q=mm[i]; } printf("%d\n",q); } #endif }
总之,无论怎么样,总能以某一种方式来学到东西!加油,hades!