bzoj 3028 食物 —— 生成函数

题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3028

式子很好推,详细可以看这篇博客:https://blog.csdn.net/wu_tongtong/article/details/78856565

所以就是要求 C(n+2,3) ,n 很大但是模数很小,可以用 Lucas 定理;

总觉得真的写了高精度和 Lucas 定理有点麻烦...而且还因为一处忘记取模 RE 了一次...

代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
int const xn=505,mod=10007;
int jc[mod+5],jcn[mod+5];
char ch[xn];
struct N{int a[xn];}n;
ll pw(ll a,int b)
{
  ll ret=1;
  for(;b;b>>=1,a=(a*a)%mod)
      if(b&1)ret=(ret*a)%mod;
  return ret;
}
int md(N x)
{
  for(int i=x.a[0];i>1;i--)
    x.a[i-1]+=(x.a[i]%mod)*10,x.a[i]=0;
  return x.a[1]%mod;//%mod
}
int C(int n,int m){return ((ll)jc[n]*jcn[m])%mod*jcn[n-m]%mod;}
int Lucas(N n,int m)
{
  if(n.a[0]<=1&&n.a[1]<2)return 0;
  int p=md(n);
  return C(p,m%mod)%mod;
}
int main()
{
  scanf("%s",ch+1); int l=n.a[0]=strlen(ch+1);
  for(int i=1;i<=l;i++)n.a[i]=ch[l-i+1]-'0';
  n.a[1]+=2;
  for(int i=1;i<=l;i++)n.a[i+1]+=n.a[i]/10,n.a[i]%=10;
  if(n.a[l+1])n.a[0]++;

  jc[0]=1;
  for(int i=1;i<mod;i++)jc[i]=(ll)jc[i-1]*i%mod;
  jcn[mod-1]=pw(jc[mod-1],mod-2);
  for(int i=mod-2;i>=0;i--)jcn[i]=(ll)jcn[i+1]*(i+1)%mod;

  printf("%d\n",Lucas(n,3));
  return 0;
}

 

posted @ 2018-11-27 15:18  Zinn  阅读(158)  评论(0编辑  收藏  举报