DP?(Lucas)

DP?(Lucas)_第1张图片
先样Pascal推一下公式,再用Lucas求值
p较小,且测试数据较多的时候需要打表

#include
#include
#include
using namespace std;
#define row 1300
#define hang 10050
int pos[hang]={0};
int reversal[row][hang]={0};
int remember[row][hang]={0};
int prime[hang],vis[hang],cnt=0;
int exp(int a,int b,int p)
{
    int ret=1;
    while(b)
    {
        if(b&1) ret=ret*a%p;
        a=a*a%p;
        b>>=1;
    }
    return ret;
}
void init()
{
    memset(vis,0,sizeof(vis));
    for(int i=2;i<hang;i++)
    {
        if(!vis[i])
        {
            prime[cnt++]=i;
            pos[i]=cnt;
            remember[cnt][0]=reversal[cnt][0]=1;
            for(int j=1,k=1;j<i;j++)
            {
                k=k*j%i;
                remember[cnt][j]=k;
                reversal[cnt][j]=exp(k,i-2,i);
            }
        }
        for(int j=0;j<cnt&&i*prime[j]<hang;j++)
        {
            vis[i*prime[j]]=1;
            if(i%prime[j]==0) break;
        }
    }
}
int cnm(int n,int m,int p)
{
    if(m>n) return 0;
    int idx=pos[p];
    int ret=remember[idx][n]*reversal[idx][m]%p;
    ret=ret*reversal[idx][n-m]%p;
    return ret;
}
int Lucas(int n,int m,int p)
{
    if(m==0) return 1;
    return cnm(n%p,m%p,p)*Lucas(n/p,m/p,p)%p;
}
int main()
{
    int cas=1,n,m,p;
    init();
    while(~scanf("%d %d %d",&n,&m,&p))
    {
        if(2*m>n) m=n-m;
        printf("Case #%d: %d\n",cas++,((Lucas(n+1,m,p)+n-m)%p+p)%p);
    }
    return 0;
}

以下是未打表的方式

#include
#include
#include
using namespace std;
typedef long long ll;
ll power(ll p,ll e,ll m)
{
    ll d=1,t=p;
    while(e>0)
    {
        if(e&1) d=(d*t)%m;
        e/=2;
        t=(t*t)%m;
    }
    return d;
}
ll cm(ll n,ll m,ll p)
{
    ll i,ans=1,a,b;
    for(i=0;i<m;i++)
    {
        a=(n-i)%p;
        b=(m-i)%p;
        ans=ans*(a*power(b,p-2,p)%p)%p;
    }
    return ans;
}
ll Lucas(ll n,ll m,ll p)
{
    if(m==0) return 1;
    return cm(n%p,m%p,p)*Lucas(n/p,m/p,p)%p;
}
int main()
{
    ll n,m,p;
    int cas=1;
    while(~scanf("%lld %lld %lld",&n,&m,&p))
    {
        if(2*m>n) m=n-m;
        printf("Case #%d %lld\n",cas++,(((Lucas(n+1,m,p)+n-m)%p+p)%p));
    }
    return 0;
}

你可能感兴趣的:(DP?(Lucas))