题意:

给出n、m、k 求C(n,k)*H(n-k)%m的值 H(n-k)为错排公式

题解:

先算H(n-k)

计算H(n)有个通式:

H(n)=(-1)^n+((-1)^(n-1))n+((-1)^(n-2))n(n-1)+...+n(n-1)(n-2)...3

证明详见维基百科:

http://zh.wikipedia.org/wiki/%E9%94%99%E6%8E%92%E9%97%AE%E9%A2%98#.E7.AE.80.E5.8C.96.E5.85.AC.E5.BC.8F

因为我们是要算H(n-k)mod m的值 显然他的前不超过m项是>0的 而其它都为0 枚举求解即可

_________________________________________________________________________________

再说C(n,k)%m

我们知道世界上有个叫 Lucas 定理的东西:

C(n, m) % p = C(n / p, m / p) * C(n % p, m % p) % p

但是它要求p是质数 所以它和本题的正解没什么关系- -

_________________________________________________________________________________

由于除的数可能不与m互质 所以不能用乘法逆元

不妨将m分解 m=p1^a1*p2^a2*...*pn^an

分别计算C(n,k)%(pi^ai) 的值 最后用中国剩余定理计算答案

于是问题转换为求C(n,k)%(p^a)的值

C(n,k)=n!/((n-k)!*k!)

为了让乘法逆元能能使用 只要将n!、(n-k)!、k! 所有p的倍数 提出来单独计算即可

如果n比较小 枚举计算不为p的倍数的数的积即可 但是这里n<=10^9 我们就需要用一些比较高端的方法

设A(n)=(1*2*..*(p-1)*(p+1)*...*(2p-1)*(2p+1)*...*n)

n!=A(n)*(p*2p*...*(n/p)p)

=A(n)*(n/p)!*p^(n/p)

=A(n)*A(n/p)*(n/p/p)!*p^(n/p/p)*p^(n/p)

=...

就是对n!不断的分解为A(n)*(n/p)!*p^(n/p) 再递归处理(n/p)! 直到n/p为0

当然在计算的同时 要累加/减 p的指数sum

这样就能求出C(n,k)不包含p的乘积了 最后再乘p^sum 即为C(n,k)%(p^a)

_________________________________________________________________________________

问题结束了吗- - 显然木有 对于A(n)还需要用O(n)的时间求出 TLE!

设r=p^a

这里A(n)的值是要模r的 我们可以这样转换

A(n)=1*2*..*(p-1)*(p+1)*...*(2p-1)*(2p+1)*...*n

=(1*2*...*(r-1))*((r+1)*(r+2)*...*(2r-1))*(...*n)

=(1*2*...*(r-1))*(1*2*...*(r-1))*...*(1*2*...*n%r) (mod r)

我们就可以预处理save[i]存下1*2*...*i (p的倍数不乘,i<=r-1)

A(n)=save[r-1]^(n/r)*save[n%r] 快速幂就可用log(n)的时间求出A

加上预处理O(r) r<=m<=10^5

最后乘m的质因数的个数blabla- -具体多少我也不知道了 反正能过

_________________________________________________________________________________

代码:

 #include <cstdio>
typedef long long ll;
const ll M=;
ll n,k,m,t,a[M],r[M],ans,p[M],pri[M],bo[M],zs[M],save[M],tot;
void makepri(){
for (ll i=;i<M;i++){
if (!bo[i]) pri[++pri[]]=i;
for (ll j=;j<=pri[] && i*pri[j]<M;j++){
bo[i*pri[j]]=;
if (!(i%pri[j])) break;
}
}
}
ll mi(ll a,ll b,ll mo){
ll res=%mo;
for (;b;b>>=){
if (b&) res=res*a%mo;
a=a*a%mo;
}
return res;
}
ll extgcd(ll &x,ll &y,ll a,ll b){
if (!b){
x=,y=;
return a;
}else{
ll res=extgcd(x,y,b,a%b);
ll t=x;
x=y;
y=t-a/b*y;
return res;
}
}
ll getny(ll a,ll b){
ll x,y,gc=extgcd(x,y,a,b),mo=b/gc;
x=(x%mo+mo)%mo;
return x;
} void makep(){
p[]=r[]=;
for (ll i=,x=m;i<=pri[] && x>;i++)
if (!(x%pri[i])){
p[++p[]]=pri[i];
r[++r[]]=;
while (!(x%pri[i])) x/=pri[i],r[r[]]*=pri[i];
}
}
void makesave(ll t){
save[]=;
for (ll i=,x=;i<=r[t];i++){
if (i%p[t]) x=x*i%r[t];
save[i]=x;
}
}
ll jc(ll n,ll t,ll &z,ll bo){
if (!n) return ;
z+=bo*(n/p[t]);
return mi(save[r[t]],n/r[t],r[t])*save[n%r[t]]%r[t]*jc(n/p[t],t,z,bo)%r[t];
}
ll getc(){
makep();
for (ll i=;i<=p[];i++){
zs[i]=;
makesave(i);
a[i]=jc(n,i,zs[i],)*getny(jc(n-k,i,zs[i],-)*jc(k,i,zs[i],-)%r[i],r[i])%r[i];
a[i]=a[i]*mi(p[i],zs[i],r[i])%r[i];
}
ll res=;
for (ll i=;i<=p[];i++)
res=(res+m/r[i]*getny(m/r[i],r[i])%m*a[i]%m)%m;
return res;
} ll geth(ll n){
if (n==) return ;
ll res=(n&) ? - : ;
for (ll i=n,x=n*res*-%m;i>= && x;x=x*(--i)*-%m)
res=((res+x)%m+m)%m;
return res;
} int main(){
scanf("%I64d",&t);
makepri();
for (ll i=;i<=t;i++){
tot=i;
scanf("%I64d%I64d%I64d",&n,&k,&m);
ans=(getc()*geth(n-k)%m+m)%m;
printf("Case %I64d: %I64d\n",i,ans);
}
}

注:这个代码能过hdu的数据但是不能过spoj的... 可能有点小bug- -?(我说spoj → →)

【spoj SEQN】【hdu 3439】Sequence的更多相关文章

  1. 【改革春风吹满地 HDU - 2036 】【计算几何-----利用叉积计算多边形的面积】

    利用叉积计算多边形的面积 我们都知道计算三角形的面积时可以用两个邻边对应向量积(叉积)的绝对值的一半表示,那么同样,对于多边形,我们可以以多边形上的一个点为源点,作过该点并且过多边形其他点中的某一个的 ...

  2. 【 SPOJ - GRASSPLA】 Grass Planting (树链剖分+树状数组)

    54  种草约翰有 N 个牧场,编号为 1 到 N.它们之间有 N − 1 条道路,每条道路连接两个牧场.通过这些道路,所有牧场都是连通的.刚开始的时候,所有道路都是光秃秃的,没有青草.约翰会在一些道 ...

  3. 【HDU 2255】奔小康赚大钱 (最佳二分匹配KM算法)

    奔小康赚大钱 Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Subm ...

  4. 【二分】【最长上升子序列】HDU 5489 Removed Interval (2015 ACM/ICPC Asia Regional Hefei Online)

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5489 题目大意: 一个N(N<=100000)个数的序列,要从中去掉相邻的L个数(去掉整个区间 ...

  5. 【贪心】【模拟】HDU 5491 The Next (2015 ACM/ICPC Asia Regional Hefei Online)

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5491 题目大意: 一个数D(0<=D<231),求比D大的第一个满足:二进制下1个个数在 ...

  6. 【动态规划】【二分】【最长上升子序列】HDU 5773 The All-purpose Zero

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5773 题目大意: T组数据,n个数(n<=100000),求最长上升子序列长度(0可以替代任何 ...

  7. 【动态规划】【KMP】HDU 5763 Another Meaning

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5763 题目大意: T组数据,给两个字符串s1,s2(len<=100000),s2可以被解读成 ...

  8. 【归并排序】【逆序数】HDU 5775 Bubble Sort

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5775 题目大意: 冒泡排序的规则如下,一开始给定1~n的一个排列,求每个数字在排序过程中出现的最远端 ...

  9. 【中国剩余定理】【容斥原理】【快速乘法】【数论】HDU 5768 Lucky7

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5768 题目大意: T组数据,求L~R中满足:1.是7的倍数,2.对n个素数有 %pi!=ai  的数 ...

随机推荐

  1. Spark中shuffle的触发和调度

    Spark中的shuffle是在干嘛? Shuffle在Spark中即是把父RDD中的KV对按照Key重新分区,从而得到一个新的RDD.也就是说原本同属于父RDD同一个分区的数据需要进入到子RDD的不 ...

  2. C++11 FAQ中文版--转

    更新至英文版October 3, 2012 译者前言: 经过C++标准委员会的不懈努力,最新的ISO C++标准C++11,也即是原来的C++0x,已经正式发布了.让我们欢迎C++11! 今天获得St ...

  3. [itint5]摆放窗口

    http://www.itint5.com/oj/#47 一种做法是:把矩形所占的方格都设为-1,就是个最大子矩阵和问题.复杂度o(w^2*h)或o(w*h^2),空间W*H猜想应用场景是:电脑屏幕上 ...

  4. autocapticalize和autocorrect

    首字母自动大写autocapitalize 在 iOS 中,用户可以手动开启「首字母自动大写」功能,这样输入英文的时候,首字母便会自动大写.但是,有些时候并不希望一直是首字母大写的.比如用户名这个字段 ...

  5. node.js 模块和包

    Node.js 的模块和包机制的实现参照了 CommonJS 的标准,但并未完全遵循.不过两者的区别并不大,一般来说你大可不必担心,只有当你试图制作一个除了支持 Node.js之外还要支持其他平台的模 ...

  6. 约瑟夫环问题-循环链表VS数组

    2013-08-18 21:27:50 循环链表.数组解决约瑟夫环问题的比较 注意几点: 循环链表的建立不难,在删除循环链表中元素时,用pCur->next != pCur判断结束: 每一轮计数 ...

  7. OM Price Lists

      --select * --from org_organization_definitions; --execute fnd_client_info.set_org_context(111); -- ...

  8. Android开发之读写联系人

    读写联系人需要用到android的ContentProvider 同时需要读和写联系人的权限 需要使用到联系人数据库中的 * raw_contacts表: * contact_id:联系人id * d ...

  9. ListView使用CursorAdapter增加和删除item

    @Override protected void onCreate(Bundle savedInstanceState) { // TODO 自动生成的方法存根 super.onCreate(save ...

  10. 1210. Kind Spirits(spfa)

    1210 简单模版题 敲个spfa还得瞟下模版.. #include <iostream> #include<cstdio> #include<cstring> # ...