码迷,mamicode.com
首页 > 其他好文 > 详细

HDU 5793 A Boring Question (费马小定理) ---2016杭电多校联合第六场

时间:2016-08-04 21:08:38      阅读:211      评论:0      收藏:0      [点我收藏+]

标签:

A Boring Question

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 156    Accepted Submission(s): 72


Problem Description
There are an equation.
0k1,k2,?kmn1?j<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;
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,(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
 

 

Recommend
wange2014
 
题意:有m个数,求c(k2,k1)*c(k3,k2).....*c(km,km-1)的值,每个数的值在[0,n]之间,求所有情况的值的总和。
题解:首先看题目中的条件 And (kj+1kj)=0 while kj+1<kj 所以我们只需要考虑非递减序列即可. 也就是说把该问题转化为n的阶乘除以组成n的m个数的各自阶乘的积,首先进行打表:

#include<iostream> #include<cstring> #include<cstdio> using namespace std; int n,m; long long C[1005][1005]; long long mod = 1000000007; long long cal(int cur,int pre) { if(cur==m+1) return 1; long long ans = 0; for(int i=pre;i<=n;i++) { //printf("%lld\n",C[i][pre]); ans+=C[i][pre]*cal(cur+1,i)%mod; ans%=mod; } return ans; } int main() { C[0][0] = 1; C[1][0]=C[1][1]=1; for(int i=2;i<=1000;i++) { C[i][0] = 1; C[i][i] = 1; for(int j=1;j<i;j++) { C[i][j] = (C[i-1][j] + C[i-1][j-1])%mod; } } int data[10][10]; memset(data,0,sizeof(data)); for(int j=2;j<=5;j++) { for(int i=0;i<=5;i++) { n=i,m=j; printf("n: %d m: %d ",n,m); printf("%lld\n",cal(1,0)); } } while(scanf("%d%d",&n,&m)!=EOF) { printf("%lld\n",cal(1,0)); } }

运行结果如下:

技术分享

仔细观察结果我们可以发现,这是等比数列前n项和,即m^ 0+m^1+m^ 2+m^3+.....+m ^n=(m^(n+1)-1)/(m-1);题目中的数据是对mod=1e9+7取模的,我们知道这是一个素数,且m的范围是int,所以gcd(m,mod)=1; 所以满足费马小定理的条件,根据费马小定理我们得知m-1对mod的逆元为(m-1)^(mod-2); ans=(m^(n+1)-1)%mod*(m-1)^(mod-2)%mod;利用快速幂即可求出结果。

AC代码:

#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
using namespace std;
typedef long long ll;
const int mod=1000000007;
ll pow1(ll a,ll b)
{
    ll ans=1;
    while(b)
    {
        if(b&1)
        {
            ans=ans*a%mod;
        }
        b>>=1;
        a=a*a%mod;
    }
    return ans;
}
int main()
{
    int t;
    ll n,m;
    cin>>t;
    while(t--)
    {
        cin>>n>>m;
        ll ans1,ans2,ans3;
        ans1=(pow1(m,n+1)-1+mod)%mod;
        ans2=(pow1(m-1,mod-2)+mod)%mod;
        ans3=ans1*ans2%mod;
        //cout<<pow1(2,4)<<endl;
        //cout<<ans1<<endl<<ans2<<endl;
        cout<<ans3<<endl;
    }
    return 0;
}

 官方给出的公式推导表示没看懂。

技术分享

HDU 5793 A Boring Question (费马小定理) ---2016杭电多校联合第六场

标签:

原文地址:http://www.cnblogs.com/Ritchie/p/5737974.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!