本文主要是介绍HDU5478 Can you find it【同余问题】,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
题目链接:
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 __int64
using 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;
}
这篇关于HDU5478 Can you find it【同余问题】的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!