Codeforces Round #305 (Div. 2) C. Mike and Frog +B. Mike and Fun

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!

时间: 2024-10-02 19:08:11

Codeforces Round #305 (Div. 2) C. Mike and Frog +B. Mike and Fun的相关文章

暴力 Codeforces Round #305 (Div. 2) B. Mike and Fun

题目传送门 1 /* 2 暴力:每次更新该行的num[],然后暴力找出最优解就可以了:) 3 */ 4 #include <cstdio> 5 #include <cstring> 6 #include <iostream> 7 #include <algorithm> 8 #include <string> 9 using namespace std; 10 11 const int MAXN = 5e2 + 10; 12 const int

set+线段树 Codeforces Round #305 (Div. 2) D. Mike and Feet

题目传送门 1 /* 2 题意:对于长度为x的子序列,每个序列存放为最小值,输出长度为x的子序列的最大值 3 set+线段树:线段树每个结点存放长度为rt的最大值,更新:先升序排序,逐个添加到set中 4 查找左右相邻的位置,更新长度为r - l - 1的最大值,感觉线段树结构体封装不错! 5 详细解释:http://blog.csdn.net/u010660276/article/details/46045777 6 其实还有其他解法,先掌握这种:) 7 */ 8 #include <cstd

数论/暴力 Codeforces Round #305 (Div. 2) C. Mike and Frog

题目传送门 1 /* 2 数论/暴力:找出第一次到a1,a2的次数,再找到完整周期p1,p2,然后以2*m为范围 3 t1,t2为各自起点开始“赛跑”,谁落后谁加一个周期,等到t1 == t2结束 4 详细解释:http://blog.csdn.net/u014357885/article/details/46044287 5 */ 6 #include <cstdio> 7 #include <algorithm> 8 #include <cstring> 9 #in

字符串处理 Codeforces Round #305 (Div. 2) A. Mike and Fax

题目传送门 1 /* 2 字符串处理:回文串是串联的,一个一个判断 3 */ 4 #include <cstdio> 5 #include <cstring> 6 #include <iostream> 7 #include <algorithm> 8 #include <string> 9 using namespace std; 10 11 const int MAXN = 1e3 + 10; 12 const int INF = 0x3f3

Codeforces Round #305 (Div. 1)

547A - Mike and Frog Solution:  先求出两种变化的第一次和第二次变化到目标的时间. 对这四个时间的具体情况需要一些特判 . 然后直接从1到2*N枚举其中一个时间的倍数,然后输出第一个满足要求的答案.  或者求出循环节后用拓展欧几里得求出最小解. 547B - Mike and Feet 题意: 给定一个长度为n(<=2*10^5)的序列,分别求出长度为(1~n)的区间的最小数的最大值. Solution: 可以先预处理以每个数为答案的最长区间. 即从每个数分别从左和

Codeforces Round #305 (Div. 1) A.B.C 解题报告

A. Mike and Frog 枚举. 先是找循环,然后很容易得出一个两元一次方程,然后可以发现解也是有循环节的,所以最小的那个肯定出现在一定范围内,否则就后面也不可能出现.假设两个变量为x,y,系数分别为z1,z2.很显然,两者的最小公倍数便是一个周期,所以如果枚举x的话,只需要枚举到z2就可以了. 细节比较多..错了好多次..比赛中也跪了.. 代码如下: #include <iostream> #include <string.h> #include <math.h&g

Codeforces Round #305 (Div. 1) B. Mike and Feet

Mike is the president of country What-The-Fatherland. There are n bears living in this country besides Mike. All of them are standing in a line and they are numbered from 1 to n from left to right. i-th bear is exactly ai feet high. A group of bears

Codeforces Round #305 (Div. 2), problem: (A) Mike and Fax

#include<iostream> #include<cstdio> #include<cstring> using namespace std; char a[1000+100]; bool judge(int m,int n) { for(int i=m;i<=(m+n)/2;i++) if(a[i]!=a[m+n-i]) return 0; return 1; } int main() { int k; while(~scanf("%s"

Codeforces Round #305 (Div. 2) E. Mike and Foam 容斥原理

在一个集合中,找和x互素的数有多少? 用容斥定理,先把每个数质因数分解(每个数至多有6个质因子),奇减偶加,就统计到和x互素的数了. 代码: #include<iostream> #include<vector> #include<algorithm> #include<cstdio> #include<cstring> using namespace std; const int N = 5*100000+10; const int maxn