Codeforces #305 C. Mike and Frog 数论

题目

题目链接:http://codeforces.com/problemset/problem/548/C

题目来源:http://acm.hust.edu.cn/vjudge/contest/view.action?cid=105944#problem/L

简要题意:求俩同余方程是否会同时成立,如果可以,求出最小的那个成立的值。

题解

首先去判断两个方程是否能够成立,次数的上限是 m

然后去算回到自己的循环节,就是达到a后多久再回到 a

然后最后根据已有的信息去暴力加上循环节然后去判断,上限还是m

题目相当坑,做起来要考虑许多边界的情况。

代码

#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <cstring>
#include <stack>
#include <queue>
#include <string>
#include <vector>
#include <set>
#include <map>
#define fi first
#define se second
using namespace std;
typedef long long LL;
typedef pair<int,int> PII;
// head
int mul(int h, int x, int y, int m) {
    return (LL(x) * h + y) % m;
}
int findPeriod(int h, int a, int x, int y, int m) {
    for (int i = 1; i <= m; i++) {
        h = mul(h, x, y, m);
        if (h == a) return i;
    }
    return 0;
}
LL solve(LL rem1, int rem2, int per1, int per2, int m) {
    for (int i = 0; i <= m; i++) {
        if (rem1 >= rem2 && (rem1-rem2) % per2 == 0) return rem1;
        rem1 += per1;
    }
    return -1;
}

int main() {
    int m, x1, y1, h1, a1, x2, y2, h2, a2;
    scanf("%d", &m);
    scanf("%d%d%d%d", &h1, &a1, &x1, &y1);
    scanf("%d%d%d%d", &h2, &a2, &x2, &y2);

    int rem1 = findPeriod(h1, a1, x1, y1, m);
    int rem2 = findPeriod(h2, a2, x2, y2, m);
    if (!rem1 || !rem2) {
        puts("-1");
        return 0;
    }

    int per1 = findPeriod(a1, a1, x1, y1, m);
    int per2 = findPeriod(a2, a2, x2, y2, m);
    if (rem1 > rem2) {
        swap(rem1, rem2);
        swap(per1, per2);
    }

    if (rem1 == rem2 || (per1 && (rem2-rem1)% per1 == 0)) {
        printf("%d\n", rem2);
    } else if (!per1 || !per2) {
        puts("-1");
    } else {
        printf("%I64d\n", solve(rem1, rem2, per1, per2, m));
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值