【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 的数 ...
随机推荐
- uva 10306
有点不同的完全背包问题 但思路还是一样的 /************************************************************************* > ...
- jquery 请求jsp传递json数据的方法
$(function() { $("a[name=hrefID]").click(function() { var id = $(this).attr("id" ...
- how to make form:checkboxes in JSP
retransmitTable.jsp file: <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix=&qu ...
- linux crontab任务调度的使用
(不推荐)可以直接将要调度的任务写入crontab任务表中 (推 荐)可以先将要完成的任务写入一个shell文件,如myTask.sh(还可能需要将该文件改为可执行的:chmod 744 myTa ...
- [mock]12月27日
一开始介绍项目,最后的反馈是,还是说得不清楚,需要再准备准备. 然后两道题,第一题是有个数组,有2*n个数字,从1~n.比如n=3的数组,{1,2,2,3,1,3}.然后两两相同的数字删除,每次删除得 ...
- thinkphp 减少文件目录
配置 'TMPL_FILE_DEPR'=>'_' 于是模板文件的格式为如:index_index.html,index_show.html .代替原来的目录结构:/index/index.htm ...
- linux下使用yum安装mysql、tomcat、httpd
一.linux下使用yum安装mysql 1.安装 查看有没有安装过: yum list installed mysql* rpm -qa | grep m ...
- 使用LinkedList实现Stack与Queue
LinkedList数据结构是一种双向的链式结构,每一个对象除了数据本身外,还有两个引用,分别指向前一个元素和后一个元素. 栈的定义栈(Stack)是限制仅在线性表的一端进行插入和删除运算.(1)通常 ...
- MapReduce编程系列 — 1:计算单词
1.代码: package com.mrdemo; import java.io.IOException; import java.util.StringTokenizer; import org.a ...
- Android开发之全屏显示的两种方法
1.通过修改清单文件中Theme,实现全屏 <application android:name=".MyApplication" android:allowBackup=&q ...