Given a prime number
C(1≤C≤2×105)
C(1≤C≤2×105), and three integers k1, b1, k2
(1≤k1,k2,b1≤109)
(1≤k1,k2,b1≤109). Please find all pairs (a, b) which satisfied the equation
ak1⋅n+b1
ak1⋅n+b1+
b
k2⋅n−k2+1
bk2⋅n−k2+1 = 0 (mod C)(n = 1, 2, 3, ...).
Please output all pairs (a, b) in lexicographical order. (1≤a,b<C) (1≤a,b<C). If there is not a pair (a, b), please output -1.
23 1 1 2
Case #1:
1 22
这道题真的很难,必须要很好的数学功底以及足够的思维能力,还有敢于尝试且有很好的总结能力。
然而很正常的,我做不出来。。
看来很多百度的,只有一种做法我比较认同,然后ac了。
消化了他的做法。在这里讲讲:(同时总结一点他人的套路,看看以后自己用不用得到)
首先,(这是第一步),就是想到用n = 1代入看看结果如何。可以得到a^k1+a^bi+b = 0.(mod c)
这样可以得到b = -(a^(k1+b1))(mod c)。
然后明显1条式子并不能推出什么。(可能这就是一个逻辑的走向吧,我想既然哦自己没能做出这题,没能自然而然的想到这样的解法,但是或许可以向他这样,遇到n的,而且n 任意的,就先从1开始代起,看看能不能得到什么)
代入2之后
a^(2*k1+b1) + b^(k2+1) = 0;
由于 b = -(a^(k1+b1))(mod c)。于是可以换掉一个a。(其实根本的就是结合两个式子求得规律)
b^(k2+1)=-a^(2*k1+b1)=b*a^(k1)。
所以很明显了
b^k2=a^k1;
于是可以只要枚举所有a,由a推出b(b = -(a^(k1+b1))(mod c))。
然后检验是否满足,满足就输出,ok,ac!
在此膜拜一下那个想出这种做法的dalao向他学习。
ac代码:
#include <stdio.h>
#include <iostream>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <queue>
#include <sstream>
#define INF 1e9
using namespace std;
typedef long long ll;
ll c,k1,k2,b1;
ll quickpow(ll a,ll b)
{
ll ans = 1;
while (b!=0)
{
if(b&1)
{
ans*=a;
ans%=c;
}
a*=a;
a%=c;
b>>=1;
}
return ans;
}//以后快速幂都写一个函数好了,方便又不会乱
bool judge(ll a,ll b)
{
if(quickpow(a,k1)!=quickpow(b,k2))
{
return false;
}
return true;
}//判断的
int main(void)
{
int k = 1;
while (scanf("%lld %lld %lld %lld",&c,&k1,&b1,&k2)!=EOF)
{
int flag = 0;
printf("Case #%d:\n",k++);
for (ll a = 1;a < c;a++)
{
ll b = -quickpow(a,(b1+k1)%(c-1));
b = (b+c)%c;
if(judge(a,b))
{
printf("%lld %lld\n",a,b);
flag = 1;
}
}
if(!flag)
cout<<-1<<endl;
}
}//要记得用ll,一开始没用ll还错了- -