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

HDU 5793 A Boring Question (快速幂 + 乘法逆元 + 费马小定理)

2017-07-12 23:24 399 查看


A Boring Question

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

Total Submission(s): 869 Accepted Submission(s): 538



Problem Description

There are an equation.

∑0≤k1,k2,⋯km≤n∏1⩽j<m(kj+1kj)%1000000007=?

We define that (kj+1kj)=kj+1!kj!(kj+1−kj)! .
And (kj+1kj)=0 while kj+1<kj.

You have to get the answer for each n and m that
given to you.

For example,if n=1,m=3,

When k1=0,k2=0,k3=0,(k2k1)(k3k2)=1;

Whenk1=0,k2=1,k3=0,(k2k1)(k3k2)=0;

Whenk1=1,k2=0,k3=0,(k2k1)(k3k2)=0;

Whenk1=1,k2=1,k3=0,(k2k1)(k3k2)=0;

Whenk1=0,k2=0,k3=1,(k2k1)(k3k2)=1;

Whenk1=0,k2=1,k3=1,(k2k1)(k3k2)=1;

Whenk1=1,k2=0,k3=1,(k2k1)(k3k2)=0;

Whenk1=1,k2=1,k3=1,(k2k1)(k3k2)=1.

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≤109,2≤m≤109)

Output

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

Sample Input

2
1 2
2 3


Sample Output

3
13


Author

UESTC

Source

2016 Multi-University Training Contest 6

题意(对于只学了大一高数的来说,有好多知识要补):

∏ 是连续积的意思。 a≡b mod(p) 就是a b两数对于%p都有相同的数。也可以理解为(a-b)%p==0

point:

先打表找规律,得知答案为 ans=(pow(m,n+1)-1)/(m-1) mod 1000000007

我觉得这已经很难了,因为pow(n,n+1)太大,结果他还要求乘法逆元 + 费马小定理。

乘法逆元:

满足 b * k ≡ 1 (mod p) 的 k 的值就是 b 关于 p 的乘法逆元。 我们可以通过求 b 关于 p 的乘法逆元 k,将 a 乘上 k 再模 p,即 (a * k) mod p。其结果与(a / b) mod p等价

费马小原理:

对于任意整数a 、p , p为素数 , gcd(a,p) = 1 , 则 a^(p-1) ≡ 1 (mod p)

综上,使a=pow(m,n+1)-1,b=m-1。

b*b^(p-2)≡ 1 (mod p) 即逆元k=b^(p-2),即(a / b) mod p等价于(a
* b^(p-2)) mod p。再利用快速幂就行。

打表代码:

#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
int n,m,ans;
int c[7][7];
int a[7];
int aans=0;
void dfs(int cnt,int now)
{
if(cnt==m+1)
{
ans=1;
for(int i=1;i<m;i++)
{
ans*=c[a[i+1]][a[i]];
}
aans+=ans;
return;
}
for(int i=now;i<=n;i++)
{
a[cnt]=i;
dfs(cnt+1,i);
}
}

int main()
{
int k[7];

k[0]=1;
for(int i=1;i<=6;i++)
{
k[i]=k[i-1]*i;
}
for(int i=0;i<=6;i++)
{
for(int j=0;j<=i;j++)
{
c[i][j]=k[i]/(k[j]*k[i-j]);
// printf("%d %d %d\n",i,j,c[i][j]);
}
}
for(int j=2;j<=5;j++)
{
for(int i=0;i<=5;i++)
{
aans=0;
n=i,m=j;
dfs(1,0);
printf("%d %d %d\n",i,j,aans);
}
}
}




ans=(pow(m,n+1)-1)/(m-1)
mod 1000000007

ac代码:

#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
#define  ll long long
const ll p = 1000000007;
ll qkm(ll base,ll mi)
{
ll ans=1;
while(mi)
{
if(mi%2==1)
ans*=base;
base*=base,base=base%p;
mi=mi/2;
ans=ans%p;
}
return ans%p;
}

int main()
{
int T;
scanf("%d",&T);
while(T--)
{
ll n,m;
scanf("%lld %lld",&n,&m);
ll a= qkm(m,n+1)-1;
ll b= m-1;
ll ans=a*qkm(b,p-2)%p;
printf("%lld\n",ans);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: