*任意n的一道式子

Given a prime number  C(1C2×105) C(1≤C≤2×105), and three integers k1, b1, k2  (1k1,k2,b1109)   (1≤k1,k2,b1≤109). Please find all pairs (a, b) which satisfied the equation  ak1n+b1    ak1⋅n+b1+ b k2nk2+1     bk2⋅n−k2+1 = 0 (mod C)(n = 1, 2, 3, ...).
Input
There are multiple test cases (no more than 30). For each test, a single line contains four integers C, k1, b1, k2.
Output
First, please output "Case #k: ", k is the number of test case. See sample output for more detail. 
Please output all pairs (a, b) in lexicographical order.  (1a,b<C) (1≤a,b<C). If there is not a pair (a, b), please output -1.
Sample Input
23 1 1 2
Sample Output
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还错了- -


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值