给定x1,y1,x2,y2 ,m
给定h1,h2
题意: 按照公式 h1=(h1*x1+y1)%m; h2=(h2*x2+y2)%m;
经过t次变化,问你能否使得h1==a1;h2==a2;如果可以就输出t;否则输出-1
先在2*m次内枚举,前m次内求到第一次h1==a1,第二次求出循环节长度 (如果有)
如果得到st1==st2 (第一次满足h==a的起点),那么直接输出答案,
如果找不到起点,那么以后也不会找到了,输出-1;
要是都找到了起点和循环节,但是并不相同;
/*
如果h1和h2每次经过一个len1循环节后,相对的距离不变化,那么永远也不会相遇
如果他们相对距离靠近了哪怕是1,他们初始距离最大是m, 那么2*m次后,必定会相遇
*/
【这题好多坑】
1【有合法循环节但是开头几个数不一定在循环节内(即使 -1 5 7 开始循环(1 2...))】
2【没有包含a1 or a2循环节不一定输出-1(也许在前几次非循环节时就相等了)】
3【】
#include <cstdio> #include <cmath> #include <cstring> #include <string> #include <algorithm> #include <iostream> #include <queue> #include <map> #include <set> #include <vector> using namespace std; int main() { __int64 mod,h1,h2,a1,a2,x1,x2,y1,y2; scanf("%I64d",&mod); scanf("%I64d%I64d",&h1,&a1); scanf("%I64d%I64d",&x1,&y1); scanf("%I64d%I64d",&h2,&a2); scanf("%I64d%I64d",&x2,&y2); __int64 i; __int64 st1,st2,len1,len2; st1=st2=len1=len2=-1; for (i=1;i<=2*mod;i++) //如果h1能变到a1,那么走m步之内一定能达到。 并且2m步之内一定能找到第二次变成a1的点,从而得到循环节长度。 { h1=(h1*x1+y1)%mod; if (h1==a1) { if (st1==-1) st1=i; //起点 else if (len1==-1) len1=i-st1; //循环节长度 } h2=(h2*x2+y2)%mod; if (h2==a2) { if (st2==-1) st2=i; else if (len2==-1) len2=i-st2; } } if (st1==-1||st2==-1)//m次都找不到起点,永远不可能找到起点了 printf("-1\n"); else if (st1==st2) //起点相同,ok printf("%I64d\n",st1); else //分别找到了起点,但是不相等 { for (i=1;i<=2*mod;i++) //因为循环节最长是mod,所以如果答案存在 2*m次就找到了 { if (st1<st2) st1+=len1; else if (st1>st2) st2+=len2; if(st1==st2) { printf("%I64d\n",st1 ); return 0; } } printf("-1\n"); } return 0; }