poj1845 逆元,快速模幂

题目大意:

给定两个正整数,求的所有因子和对9901取余后的值。

分析:

很容易知道,先把分解得到,那么得到,那么

的所有因子和的表达式如下

因为要取模且存在除法,所以要用到逆元。

对于正整数,如果有,那么把这个同余方程中的最小正整数解叫做的逆元。

逆元一般用扩展欧几里得算法来求得,如果为素数,那么还可以根据费马小定理得到逆元为

推导过程如下

求现在来看一个逆元最常见问题,求如下表达式的值(已知

当然这个经典的问题有很多方法,最常见的就是扩展欧几里得,如果是素数,还可以用费马小定理。

但是你会发现费马小定理和扩展欧几里得算法求逆元是有局限性的,它们都会要求互素。实际上我们还有一

种通用的求逆元方法,适合所有情况。公式如下

现在我们来证明它,已知,证明步骤如下

等比数列求和公式,用如下公式即可

因为可能会很大,超过int范围,所以在快速幂时要二分乘法。

接下来就是代码了:(一定要讲乘法二分,还有取模后一定要加模)

#include <iostream>
#include <cstdio>
#include <string>
#include <cstring>
#include <fstream>
#include <algorithm>
#include <cmath>
#include <queue>
#include <stack>
#include <vector>
#include <map>
#include <set>
#include <iomanip>

using namespace std;
#pragma comment(linker, "/STACK:102400000,102400000")
#define maxn 10005
#define MOD 1000000007
#define mem(a , b) memset(a , b , sizeof(a))
#define LL long long
#define ULL long long
const long long INF=0x3fffffff;
bool prime[maxn];
int p[maxn];

void is_prime()
{
    mem(prime , true);
    int id = 0;
    prime[0] = prime[1] = false;
    for(int i = 2 ; i < maxn ; i ++)
    {
        if(prime[i])
        {
            p[id++] = i;
            int j = 2 * i;
            while(j <= maxn) prime[j] = false , j += i;
        }
    }
}

LL mulit(LL a , LL  b , LL mod)
{
    a %= mod;
    b %= mod;
    LL res = 0;
    while(b)
    {
        if(b & 1)
        {
            res = (res + a) % mod;
        }
        b >>= 1;
        a = (a + a) % mod;
    }
    return res % mod;
}

LL quick_mod(LL a , LL b , LL mod)
{
    LL res = 1;
    while(b)
    {
        if(b & 1)
        {
            res = mulit(res , a , mod);
        }
        a = mulit(a , a , mod);
        b >>= 1;
    }
    return res;
}
//ofstream  ofile;
int main()
{
    LL a , b;
    is_prime();
    while(scanf("%lld %lld",&a , &b) != EOF )
    {
        LL ans = 1;
        for(int i = 0 ; p[i] * p[i] <= a ; i++)
        {
            if(a % p[i] == 0)
            {
                int num = 0;
                while(a % p[i] == 0)
                {
                    num ++;
                    a /= p[i];
                }
                ans *= (quick_mod(p[i] , num * b+1 , 9901 *(p[i]-1) ) + (9901 *(p[i]-1))- 1) / (p[i] - 1);
                ans %= 9901;
            }
        }
        if(a > 1)
        {
            ans *= (quick_mod(a ,  b+1 , 9901 *(a-1) ) + 9901 *(a-1) - 1) / (a - 1);
            ans %= 9901;
        }
        cout << ans << endl;
    }
    return 0;
}
时间: 2024-08-29 14:56:05

poj1845 逆元,快速模幂的相关文章

【分治】快速模幂

问题 R: [分治]快速模幂 时间限制: 1 Sec  内存限制: 64 MB提交: 8  解决: 7[提交][状态][讨论版] 题目描述 试求ab%n的值,其中a.b.n均为整数范围内的数. 输入 三个整数a.b和n 输出 ab%n的值 样例输入 1 1 1 样例输出 0解题思路:快速模幂比快速幂多了取余,和另一个快速取余是一样的.有公式.代码: #include <iostream> #include <cstdio> using namespace std; //a*b %

快速模幂

问题 H: [分治]快速模幂 时间限制: 1 Sec  内存限制: 64 MB提交: 79  解决: 64[提交] [状态] [讨论版] [命题人:admin] 题目描述 试求ab%n的值,其中a.b.n均为整数范围内的数. 输入 三个整数a.b和n 输出 ab%n的值 样例输入 1 1 1 样例输出 0 1 #include <iostream> 2 3 using namespace std; 4 typedef long long ll; 5 ll fun(ll a, ll b, ll

UVA11029 Leading and Trailing【快速模幂+数学】

Apart from the novice programmers, all others know that you can't exactly represent numbers raised to some high power. For example, the C function pow(125456, 455) can be represented in double data type format, but you won't get all the digits of the

NYOJ--102--次方求模(快速求幂取模)

次方求模 时间限制:1000 ms  |  内存限制:65535 KB 难度:3 描述 求a的b次方对c取余的值 输入 第一行输入一个整数n表示测试数据的组数(n<100)每组测试只有一行,其中有三个正整数a,b,c(1=<a,b,c<=1000000000) 输出 输出a的b次方对c取余之后的结果 样例输入 3 2 3 5 3 100 10 11 12345 12345 样例输出 3 1 10481 1 /* 2 Name: NYOJ--102--次方求模 3 Copyright: ?

POJ 2447 RSA 大数分解+逆元+快速幂

链接:http://poj.org/problem?id=2447 题意: 思路:Pollard_Rho质数分解,得到两个素数因子,P,Q,求出T,E,快速幂即可得M. 代码: #include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <map> #include <cstdlib> #include <queue>

快速求幂模

今天我要介绍的是快速求幂模,在开始介绍之前,我们先看看如何快速求幂.这里我要介绍的是二分求幂. 二分求幂的原理如下: 下面,我们将这个公式转换成代码: int cifang(int a,int n)//返回值是a的n次方 { int res=1;//任何数的0次方都等于1,所以初始化为1 while(n != 0) { if(n%2 == 1)//如果n是奇数 res *= a;//就要多乘一次,即res = res*a; a = a*a; n /= 2;//二分,即n = n/2 } retu

2014 Super Training #7 F Power of Fibonacci --数学+逆元+快速幂

原题:ZOJ 3774  http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3774 ---------------------------------------------------------------------------------------------------------------------- 这题比较复杂,看这篇比较详细:http://blog.csdn.net/acdreamers/artic

快速矩阵幂+DFS构造矩阵+大数 ACdream1214 Nice Patterns Strike Back

传送门:点击打开链接 题意:告诉你矩阵大小是n*m,要求矩阵中不能有2*2的白色子矩阵或者黑色子矩阵,最后种类数模P 思路:如果不是大数,这道题还是非常有意思的..对于专门卡C++的题目也是醉了...因为n太大了,而m最大也只有5,很明显是大数上的快速矩阵幂. 问题是如何构造出矩阵出来,之前做过骨牌的题目,就是利用DFS来构造的,感觉这道题在思路上是一样的,同样也是利用DFS先构造出矩阵 然后直接大数+快速矩阵幂撸一发就行了 #include<map> #include<set>

CodeForces621E 快速矩阵幂优化dp

有时些候在用快速矩阵幂优化dp的时候,它的矩阵乘法是不那么容易被具体为题目背景的意思的,大多数时候难以理解矩阵之间相乘的实际意义,正如有时候我们不知道现在在做手头这些事情的意义,但倘若是因一个目标而去做的,正如快速矩阵幂最终会计算出答案一样,我们也最终会在这些不明意义的事情中实现目标. 题意:有 bb 个格子,每个格子有 nn 个数字,各个格子里面的数字都是相同的. 求从 bb 个格子中各取一个数字, 构成一个 bb 位数, 使得这个 bb 位数模 xx 为 kk 的方案数(同一格子内相同的数字