您的位置:首页 > 产品设计 > UI/UE

hdu 5793 A Boring Question (数学 + 快速幂 + 乘法逆元)

2016-08-04 18:46 471 查看
题目链接:hdu 5793

A Boring Question

Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)

Problem Description

There are an equation.



So the answer is 4.

Input

The first line of the input contains the only integer T,(1≤T≤10000)

Then T lines follow,the i-th line contains two integers n,m,(0≤n≤1e+9,2≤m≤1e+9)

Output

For each n and m,output the answer in a single line.

Sample Input

2

1 2

2 3

Sample Output

3

13

读题也费了点时间,其实就是给m个0到n之间的数按照组合数求出结果再两两相乘,最后再将所有可能的值加起来。

比赛时是三个人一起手算打表找规律过的,快速幂和乘法逆元还WA了一回,看来熟练度不够。

bestcoder官网博客的正儿八经题解:



找到公式后就是用快速幂算出m^(n + 1),再用扩展欧几里得模板算逆元得结果。

#include <cstdio>
#include <cmath>
#define MAX 100005
#define mod 1000000007

using namespace std;

long long multi(long long a, long long b)//快速幂
{
long long ret = 1;
while(b > 0)
{
if(b & 1)
ret = (ret * a) % mod;
a = (a * a) % mod;
b >>= 1;
}
return ret;
}

long long exgcd(long long a, long long b, long long &x, long long &y)//扩展欧几里得
{
if(!b)
{
x = 1;
y = 0;
return a;
}
long long d = exgcd(b, a % b, x, y);

long long tmp = x;
x = y;
y = tmp - a / b * y;

return d;
}

int main()
{
int T;
scanf("%d", &T);
while(T--)
{
long long n, m, x, y;
scanf("%lld %lld", &n, &m);
long long mul = (multi(m, n + 1) - 1) % mod;
long long d = exgcd(m - 1, mod, x, y);//若这里mod的位置填写mod * (m - 1),最终计算时需要让x和mod都除以d
x *= mul;
x /= d;//因为m - 1和mod是互质的,这句可以去掉。
x = (x % mod + mod) % mod;//防止最终结果为负数
printf("%lld\n", x);
}
return 0;
}


运行结果:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息