HDU 5478 Can you find it 2015ICPC上海网络赛

Can you find it

Time Limit: 8000/5000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 474    Accepted Submission(s): 219


Problem Description
Given a prime number  C(1C2×105) , and three integers k1, b1, k2  (1k1,k2,b1109) . Please find all pairs (a, b) which satisfied the equation  ak1n+b1 bk2nk2+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) . If there is not a pair (a, b), please output -1.
 

Sample Input
  
  
23 1 1 2
 

Sample Output
  
  
Case #1: 1 22
 

Source
 

题意:输入C,k1,b1,k2,求满足题中所给公式的所有a,b的值,每对按字典序升序输出。

分析:我们先将公式变一下形为:a^(k1*n)   *   a^b1   +   b^(k2*n)   *   b^(1-k2)=0(mod C)

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

在这个等式中,只有n为未知数,那么就可以看成是两个指数函数和的形式,由于质数函数的导数时刻不同,所以如果要保持在n不同时结果对C取

模仍然等于零的话,那么就要保证底数相同,只有这样他们的增长率才会相同,那么对C取模也就是不变的。这时候我们就可合并同类项了,设

X=a^k1=b^k2,那么公式变形为X*(a^b1+b^(1-k2))%C=0,即b^(1-k2)%C=(C-(a^b1)%C)%C;这是我们就可以进行枚举了,在保证a^k1==b^k2

的前提下枚举其中一个值,然后去验证另外一个值(其实你先枚举符合条件的值然后再进行底数的验证也可以)。现在为了计算方便我们将公式

变形为:(a^k1)^(n-1)   *   a^(b1+1)   +   (b^k2)^(n-1)   *   b=0(mod C) 。然后计算b的时候就能够直接利用C相减了,具体看代码怎么实现的

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cctype>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
#include<algorithm>
#include<set>
#define scnaf scanf
#define cahr char
#define bug puts("bugbugbug");
using namespace std;
typedef long long ll;
const int mod=1000000007;
const int maxn=2000+5;
const int inf=1e9;
const int maxe=200000;
typedef long long ll;
//快速幂
ll pow_mod(ll a, ll n, ll m) {
    ll res = 1;
    while(n) {
        if (n & 1) res = res * a % m;
        n >>= 1;
        a = a * a % m;
    }
    return res;
}
struct T
{
    int a,b;
    bool operator < (const T &c) const {
    if(a!=c.a)
    return a<c.a;
    return b<c.b;
    }
};
vector<T>ans;
int main()
{
    int c,k1,B1,k2,test=1;
    while(~scanf("%d%d%d%d",&c,&k1,&B1,&k2))
    {
        printf("Case #%d:\n",test++);
        B1+=k1;
        ans.clear();
        int a,b;
        for(int a=1;a<c;a++)
        {
            int ab1=pow_mod(a,B1,c);
            int b=c-ab1;
            if(b<=0||b>=c)continue;
            if(pow_mod(a,k1,c)==pow_mod(b,k2,c))
             ans.push_back((T){a,b});
        }
        sort(ans.begin(),ans.end());
        if(!ans.size()) puts("-1");
        for(int i=0;i<ans.size();i++)
            printf("%d %d\n",ans[i].a,ans[i].b);
    }
    return 0;
}

感谢赵同学给我讲题。

题目链接:点击打开链接







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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值