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

刚开始以为主要难在优化时间,结果发现其实难点在考虑周全……

首先用数组x和y保存下来h1与h2对m取余的数,并用t1、t2表示h1与h2的循环节长度,s1、s2表示首次取到a1、a2时的秒数。

当s1或s2为0时,即未从x、y中找到a1、a2,直接输出-1即可。

当s1与s2都找到后,由于部分h1与h2的数据不一定在循环节中,用x[h1]与y[h2]分别表示二者进入循环节之前的时间,先将二者较长的作为范围,从中寻找s1和s2。

若未找到,则判断s1与s2是否都未在循环节中,若都未在,则输出-1,否则进入循环节中寻找。

下面是代码

#include <algorithm>
#include <iostream>
#include <sstream>
#include <cstring>
#include <cstdlib>
#include <string>
#include <vector>
#include <cstdio>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <set>
using namespace std;
int x[1000005],y[1000005];
int main()
{
    long long m,i,a1,a2,x1,x2,y1,y2;
    long long h1,h2,t1,t2,h3,h4;
    while(cin>>m)
    {
        cin>>h1>>a1>>x1>>y1;
        cin>>h2>>a2>>x2>>y2;
        h3=h1,h4=h2;
        long long s1=0,s2=0;
        memset(x, 0, sizeof(x));
        memset(y, 0, sizeof(y));
        if(x[h1]==0) x[h1]=1;
        for(i=2;;i++)
        {
            h1=h1*x1+y1;
            h1%=m;
            if(x[h1]!=0) {t1=i-x[h1];break;}
            if(x[h1]==0) x[h1]=i;
             if(h1==a1) s1=i-1;
        }
        x[h1]-=1;
        if(y[h2]==0) y[h2]=1;
        for(i=2;;i++)
        {
            h2=h2*x2+y2;
            h2%=m;
            if(y[h2]!=0) {t2=i-y[h2];break;}
            if(y[h2]==0) y[h2]=i;
            if(h2==a2) s2=i-1;
        }
        y[h2]-=1;
        if(s1*s2==0) cout<<"-1"<<endl;
        else
        {
            {
                int flag=0;
                if(t2<t1)
                {
                    swap(t2, t1);
                    swap(s1, s2);
                }
                else if(t2==t1&&s2>s1) swap(s1, s2);
                {
                    long long max1=max(x[h1],y[h2]);
                    for (i=0; i<=t2+max1; i++)
                    {
                        if(i<max1)
                        {
                            h3=h3*x1+y1;
                            h4=h4*x2+y2;
                            h3%=m;
                            h4%=m;
                            if(h3==a1&&h4==a2) {cout<<i+1<<endl;flag=1;break;}
                            continue;
                        }
                        if(s1<=x[h1]&&s2<=y[h2]) {cout<<"-1"<<endl;flag=1;break;}
                        if(s1%t2==s2%t2) {cout<<s1<<endl;flag=1;break;}
                        s1+=t1;
                    }
                }
                    if(!flag) cout<<"-1"<<endl;
            }
        }
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值