【spoj SEQN】【hdu 3439】Sequence
题意:
给出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
证明详见维基百科:
因为我们是要算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的更多相关文章
- 【改革春风吹满地 HDU - 2036 】【计算几何-----利用叉积计算多边形的面积】
利用叉积计算多边形的面积 我们都知道计算三角形的面积时可以用两个邻边对应向量积(叉积)的绝对值的一半表示,那么同样,对于多边形,我们可以以多边形上的一个点为源点,作过该点并且过多边形其他点中的某一个的 ...
- 【 SPOJ - GRASSPLA】 Grass Planting (树链剖分+树状数组)
54 种草约翰有 N 个牧场,编号为 1 到 N.它们之间有 N − 1 条道路,每条道路连接两个牧场.通过这些道路,所有牧场都是连通的.刚开始的时候,所有道路都是光秃秃的,没有青草.约翰会在一些道 ...
- 【HDU 2255】奔小康赚大钱 (最佳二分匹配KM算法)
奔小康赚大钱 Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Subm ...
- 【二分】【最长上升子序列】HDU 5489 Removed Interval (2015 ACM/ICPC Asia Regional Hefei Online)
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5489 题目大意: 一个N(N<=100000)个数的序列,要从中去掉相邻的L个数(去掉整个区间 ...
- 【贪心】【模拟】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个个数在 ...
- 【动态规划】【二分】【最长上升子序列】HDU 5773 The All-purpose Zero
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5773 题目大意: T组数据,n个数(n<=100000),求最长上升子序列长度(0可以替代任何 ...
- 【动态规划】【KMP】HDU 5763 Another Meaning
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5763 题目大意: T组数据,给两个字符串s1,s2(len<=100000),s2可以被解读成 ...
- 【归并排序】【逆序数】HDU 5775 Bubble Sort
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5775 题目大意: 冒泡排序的规则如下,一开始给定1~n的一个排列,求每个数字在排序过程中出现的最远端 ...
- 【中国剩余定理】【容斥原理】【快速乘法】【数论】HDU 5768 Lucky7
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5768 题目大意: T组数据,求L~R中满足:1.是7的倍数,2.对n个素数有 %pi!=ai 的数 ...
随机推荐
- console中应用MFC类的方法
1.添加#include <afx.h>或者<afxwin.h> 这时会报错1>c:\program files\microsoft visual studio 8\vc ...
- aop aspect
所以“<aop:aspect>”实际上是定义横切逻辑,就是在连接点上做什么,“<aop:advisor>”则定义了在哪些连接点应用什么<aop:aspect>.Sp ...
- [Unity菜鸟] 摄像机视角控制
1. 摄像机预览物体 上下左右远近 把CameraFollow脚本赋给Camera,把要观察的对象赋给target using UnityEngine; using System.Collection ...
- Some projects cannot be imported because they already exist in the workspace
原文地址: Some projects cannot be imported because they already exist in the workspace - 浅尝辄止的博客 - 博客频道 ...
- AC题目简解-dp
dp类:A - Bridging signals ZOJ 3627 POJ1631 HDU1950给出一个从1-n的数字排列,求最长上升子序列长度.直接说解法吧.新开一个数组d,d[i]表示的是能构成 ...
- IIS8报错 403 404
当IIS报403错误,而打开目录浏览权限后,又出404错误,这种错误很可能是.net的版本安装问题 注意勾选上asp.net4.5
- IIS会话过期的问题/WCF日志管理
http://technet.microsoft.com/zh-cn/library/cc725624(v=ws.10).aspx http://msdn.microsoft.com/zh-cn/li ...
- Ubuntu忘记管理员密码
Ubuntu中不小心把管理员密码忘记了,真叫人头大. 现提供一个解决方案: 1.重启 Ubuntu 系统,按 Esc 进入GRUB 菜单界面,如下图: 2.选择recovery mode. (第二个) ...
- Codeforces 364A - Matrix
原题地址:http://codeforces.com/problemset/problem/364/A 题目大意: 给定一个数字a(0 ≤ a ≤ 109)和一个数列s(每个数都是一位,长度不超过40 ...
- 让Windows Server 2008 + IIS 7+ ASP.NET 支持10万个同时请求
具体设置如下: 1. 调整IIS 7应用程序池队列长度 由原来的默认1000改为65535. IIS Manager > ApplicationPools > Advanced Setti ...