【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 的数 ...
随机推荐
- Java 程序检查远程服务器状态
通常我们以命令的方式判断远程服务器是否正常运行有两种方式,ping 或 telnet 一个远程端口.假设我们要检查的远程服务器都是 Linux 系统. 从 JDK 1.5 以后, InetAddres ...
- HDU1796+容斥原理
给定n和m个数,询问在小于n的数中 有多少个能整除m中的某个数.. 容斥原理. PS:注意64位整数! /* 容斥原理 */ #include<stdio.h> #include<s ...
- hdu 4035 Maze 概率DP
题意: 有n个房间,由n-1条隧道连通起来,实际上就形成了一棵树, 从结点1出发,开始走,在每个结点i都有3种可能: 1.被杀死,回到结点1处(概率为ki) ...
- *[topcoder]GooseTattarrattatDiv1
http://community.topcoder.com/stat?c=problem_statement&pm=12730&rd=15701 这道题有点意思.首先把字符串变成回文, ...
- linux xxd 命令
http://www.cnblogs.com/openix/archive/2012/04/23/2466320.html xxd -i dht.jpg dht.h
- vs 下 opengl 配置问题
项目 -->选择属性 C\C++-->preprocessor-->preprocessor definition 添加GLUT_BUILDING_LIB,中间用分号隔开. 然后点击 ...
- C#+SQL数据库备份和还原
使用前要导入SQLDMO.dll(在com组件中导入Microsoft SQLDMO Object Library即可) /// /// DbOper类,主要应用SQLDMO实现对Microsoft ...
- 理解TCP/IP协议
TCP/IP协议是Transmission Control Protocol/Internet Protocol的简写,中译名为传输控制协议/因特网互联协议. 单从TCP/IP协议这个名称看,好多人误 ...
- xml--通过jdom解析及生产XML
JDOM是一种使用 XML 的独特 Java 工具包,用于快速开发 XML 应用程序.它的设计包含 Java 语言的语法乃至语义. JAXP (用于 XML 语法分析的 Java API)包含了三个软 ...
- Maximum Allowed Error 7 错误解决
http://blog.csdn.net/lyx123/article/details/6238167 这段时间,一直在做WINCE 的应用,后来将NK做大后,必须修改EBOOT,以便能够提供较大的空 ...