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

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.
0k1,k2,kmn1j<m(kj+1kj)%1000000007=?
We define that  (kj+1kj)=kj+1!kj!(kj+1kj)!  . 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 ;
When k1=0,k2=1,k3=0,(k2k1)(k3k2)=0 ;
When k1=1,k2=0,k3=0,(k2k1)(k3k2)=0 ;
When k1=1,k2=1,k3=0,(k2k1)(k3k2)=0 ;
When k1=0,k2=0,k3=1,(k2k1)(k3k2)=1 ;
When k1=0,k2=1,k3=1,(k2k1)(k3k2)=1 ;
When k1=1,k2=0,k3=1,(k2k1)(k3k2)=0 ;
When k1=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 , (1T10000)
Then  T  lines follow,the i-th line contains two integers  n , m , (0n109,2m109)
 

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);
    }
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值