HDU5478 Can you find it【同余问题】

来源:互联网 发布:单片机与嵌入式 编辑:程序博客网 时间:2024/05/01 05:13

题目链接:

http://acm.hdu.edu.cn/showproblem.php?pid=5478


题目大意:

给你一个素数 C(1 <= C <= 2*10^5) 和整数 k1、b1、k2(1 <= k1,k2,b1 <= 10^9)。

找出有多少个(a,b)满足 a^(k1*n+b1) + b^(k2*n-k2+1) ≡ 0(mod C)(n = 1,2,3,…)

如果找不到则输出 -1。


解题思路:

先来看同余的几个基本定理。

1. a ≡ b(mod m),当且仅当 m | (a-b)。

2. a ≡ b(mod m),当且仅当存在整数 k,使得 a = b + k*m。

3. 同余关系是等价关系,即

(1) 自反性:a ≡ a(mod m)。

(2) 对称性:若 a ≡ b(mod m),则 b ≡ a(mod m)。

(3) 传递性:若 a ≡ b(mod m),b ≡ c(mod m),则 a ≡ c(mod m)。

4. 若 a,b,c 是整数,m 是正整数,且 a ≡ b(mod m),则

(1) a + c ≡ b + c(mod m);

(2) a - c ≡ b - c(mod m);

(3) a*c ≡ b*c(mod m);

5. 设 a,b,c,d 为整数,m 为正整数,若 a ≡ b(mod m),c ≡ d(mod m),则

(1) a*x + c*y ≡ b*x + d*y(mod m)

(2) a*c ≡ b*d(mod m),即同余式可以相乘;

(3) a^n ≡ b^n(mod m),其中 n > 0;

(4) f(a) ≡ f(b)(mod m),其中 f(x) 为任一整数系数多项式。

6. 设 a,b,c,d 为整数,m 为正整数,则

(1) 若 a ≡ b(mod m),且 d | m,则 a ≡ b(mod d);

(2) 若 a ≡ b(mod m),则 gcd(a,m)  = gcd(b,m);  

(3) a ≡ b(mod mi)(1 <= i <= n)同时成立,当且仅当 a ≡ b(mod [m1,m2,…,mn])。

7. 若 a*c ≡ b*c(mod m),且 gcd(c,m) = d,则 a ≡ b(mod m/d)。

再看这倒题:

因为恒等式要对所有的 n(正整数)成立,所以要让式子变为对 n 无关的样子。

a^(k1*n+b1) + b^(k2*n-k2+1) ≡ 0(mod C)  

a^(k1*n+b1) ≡ -1*b^(k2*n-k2+1)(mod C)  定理4(2)

a^(k1*n+b1) ≡ (C-1)*b^(k2*n-k2+1)(mod C) 

a^(k1*n)*a^b1 ≡ b^(k2*n)*(C-1)*b^(1-k2)(mod C)

a^b1 * b^(k2-1) / (C-1) ≡ (b^k2 / a^k1)^n(mod C) 定理7

这样来看,只有右边等式为 1,才能使无论 n 为多少,式子都恒成立,所以可以得到两个

式子:

a^b1 * b^(k2-1) ≡ (C-1)(mod C)

a^k1 = b^k2

在原式 a^(k1*n+b1) + b^(k2*n-k2+1) ≡ 0(mod C) 中,n = 1 时,a^(k1+b1) + b = 0,

则对于确定的 a,对应的 b 只有一个,那么现在枚举 a,然后计算出 b,再去判断 (a,b)是

否满足上述两式。


AC代码:

#include<iostream>#include<algorithm>#include<cstdio>#include<cstring>#define LL __int64using namespace std;const int MAXN = 200100;LL C,k1,k2,b1;LL QuickPow(LL a,LL b){    LL ans = 1;    while(b)    {        if(b & 1)            ans = ans*a % C;        a = a*a % C;        b >>= 1;    }    return ans;}bool Judge(LL a,LL b){    return QuickPow(a,k1) == QuickPow(b,k2) && 1LL*QuickPow(a,b1)*QuickPow(b,k2-1)%C == C-1;}int main(){    int kase = 0;    while(~scanf("%I64d%64d%64d%64d",&C,&k1,&b1,&k2))    {        printf("Case #%d:\n",++kase);        bool flag = false;        for(LL i = 1; i < C; ++i)        {            LL b = C - QuickPow(i,k1+b1);            if(Judge(i,b))            {                flag = true;                printf("%I64d %I64d\n",i,b);            }        }        if(!flag)            printf("-1\n");    }    return 0;}


0 0
原创粉丝点击