求\(\binom {n}{m} mod\) \(p\) 的值,不保证\(p\)为质数
(扩展和普通算法毫无关系)
由于\(p\)不是质数,我们考虑[SDOI2010]古代猪文 - 洛谷中的处理方法:将\(p\)质因数分解得:
所以我们考虑计算$\binom nm mod $ \({p_i}^{c_i}\)的值,再用CRT合并即可
展开上式:
我们发现由于\(m!(n - m)!\)中可能含有因数p,我们无法求出\(m!(n - m)!\)模\({p_i}^{c_i}\)意义下的逆元,所以我们考虑除去三个数中所有的p因子,假设\(p^x | n!\)且\(p^{x+1} \nmid n!\),即x是\(n!\)中p因子的个数(对于\(m!\)和\((n - m)!\)同理)
由于\(\frac{n!}{p^x}、\frac{m!}{p^y}、\frac{(n - m)!}{p^z}\)三式同构,我们考虑计算其中一个式子(以下用\(p\)替换\(p_i\))
展开为
提出p的倍数
即
如果暴力计算\(\Pi_{i = 1;i \not\equiv 0}^{n}\)复杂度过高,不难发现其有一个循环节,即每过p个数就会少乘上第p个数,又因为\({p_i}^{c_i}+ r \equiv r\ mod\ {p_i}^{c_i}\),所以我们以\({p_i}^{c_i}\)作为这个循环节
对于\(\Pi_{i = 1;i \not\equiv 0}^{p^{c_i}}\)和\(\Pi_{i = {p^{c_i}}\lfloor\frac{n}{p^{c_i}}\rfloor;i \not\equiv 0}^{n}\),暴力计算即可
不管\(x\)取何值,最终p因子都会消除,所以计算时去掉\(p^{\lfloor \frac np \rfloor}\)
因为\(\lfloor \frac np \rfloor!\)中可能含有p因子,所以我们将其进行递归:
设\(f(n) = \frac {n!}{p^x}\ mod \ {p}^{c_i}\),则:
根据此式递推即可,时间复杂度为\(O(log_pn)\),不会证明qwq
对于外面的\(p^{x - y - z}\),只要求出\(x、y、z\)的值就可以计算了
观察以上函数可知,每次在\(f(n)\)这一层就会去掉\(\lfloor \frac np \rfloor\)个p因子
定义\(g(n)\)为\(n!\)中p因子的个数,则:
此结论对于其他题目也同样有效
所以原始式子就转化成了
因为去掉了p因子,所以\(f(m)\)和\(f(n - m)\)与\(p^{c_i}\)互质,可以求逆元
因为\(p^{c_i}\)不是质数,不能直接用费马小定理计算,所以我们采用\(exgcd\)求逆元
最后进行CRT合并答案
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll res[101],d[101],zs[101],tot = 0,M[101];
inline ll g(ll n,ll p)
{
if(n == 0) return 0;
return g(n / p,p) + n / p;
}
inline ll ksm(ll base,ll pts,ll mod)
{
ll ret = 1;
for(;pts > 0;pts >>= 1,base = base * base % mod)
if(pts & 1)
ret = ret * base % mod;
return ret;
}
inline ll F(ll n,ll p,ll k)
{
if(n == 0) return 1;
ll P = ksm(p,k,1e18 + 1);
ll mul = 1;
for(ll i = 1;i <= P;i++)
if(i % p)
mul = mul * i % P;
mul = ksm(mul,n / P,P);
for(ll i = P * (n / P);i <= n;i++)
if(i % p)
mul = mul * (i % P) % P;
return F(n / p,p,k) * mul % P;
}
inline void exgcd(ll a,ll b,ll &x,ll &y)
{
if(b == 0)
{
x = 1;
y = 0;
return;
}
ll tmp;
exgcd(b,a % b,x,y);
tmp = y;
y = x - (a / b) * y;
x = tmp;
}
inline ll exlucas(ll n,ll m,ll p)
{
ll tmp = p;
for(ll i = 2;i <= sqrt(p);i++)
{
if(tmp % i == 0)
{
++tot;
d[tot] = i;
while(tmp % i == 0)
{
tmp /= i;
++zs[tot];
}
}
}
if(tmp != 1)
{
++tot;
d[tot] = tmp;
zs[tot] = 1;
}
for(int i = 1;i <= tot;i++)
{
ll P = ksm(d[i],zs[i],1e18 + 1);
ll inv1,inv2,yy;
exgcd(F(m,d[i],zs[i]),P,inv1,yy);
exgcd(F(n - m,d[i],zs[i]),P,inv2,yy);
inv1 = (inv1 % P + P) % P;
inv2 = (inv2 % P + P) % P;
res[i] = F(n,d[i],zs[i]) * inv1 % P * inv2 % P * ksm(d[i],g(n,d[i]) - g(m,d[i]) - g(n - m,d[i]),P) % P;
M[i] = P;
}
ll ans = 0;
for(int i = 1;i <= tot;i++)
{
ll inv,yy;
exgcd(p / M[i],M[i],inv,yy);
inv = (inv % M[i] + M[i]) % M[i];
ans = (ans + res[i] * (p / M[i]) % p * inv % p) % p;
}
return ans;
}
int main()
{
ll n,m,p;
cin>>n>>m>>p;
cout<<exlucas(n,m,p);
return 0;
}
我正在编写一个包含C扩展的gem。通常当我写一个gem时,我会遵循TDD的过程,我会写一个失败的规范,然后处理代码直到它通过,等等......在“ext/mygem/mygem.c”中我的C扩展和在gemspec的“扩展”中配置的有效extconf.rb,如何运行我的规范并仍然加载我的C扩展?当我更改C代码时,我需要采取哪些步骤来重新编译代码?这可能是个愚蠢的问题,但是从我的gem的开发源代码树中输入“bundleinstall”不会构建任何native扩展。当我手动运行rubyext/mygem/extconf.rb时,我确实得到了一个Makefile(在整个项目的根目录中),然后当
我正在使用puppet为ruby程序提供一组常量。我需要提供一组主机名,我的程序将对其进行迭代。在我之前使用的bash脚本中,我只是将它作为一个puppet变量hosts=>"host1,host2"我将其提供给bash脚本作为HOSTS=显然这对ruby不太适用——我需要它的格式hosts=["host1","host2"]自从phosts和putsmy_array.inspect提供输出["host1","host2"]我希望使用其中之一。不幸的是,我终其一生都无法弄清楚如何让它发挥作用。我尝试了以下各项:我发现某处他们指出我需要在函数调用前放置“function_”……这
我想这样组织C源代码:+/||___+ext||||___+native_extension||||___+lib||||||___(Sourcefilesarekeptinhere-maycontainsub-folders)||||___native_extension.c||___native_extension.h||___extconf.rb||___+lib||||___(Rubysourcecode)||___Rakefile我无法使此设置与mkmf一起正常工作。native_extension/lib中的文件(包含在native_extension.c中)将被完全忽略。
首先回顾一下拉格朗日定理的内容:函数f(x)是在闭区间[a,b]上连续、开区间(a,b)上可导的函数,那么至少存在一个,使得:通过这个表达式我们可以知道,f(x)是函数的主体,a和b可以看作是主体函数f(x)中所取的两个值。那么可以有, 也就意味着我们可以用来替换 这种替换可以用在求某些多项式差的极限中。方法: 外层函数f(x)是一致的,并且h(x)和g(x)是等价无穷小。此时,利用拉格朗日定理,将原式替换为 ,再进行求解,往往会省去复合函数求极限的很多麻烦。使用要注意:1.要先找到主体函数f(x),即外层函数必须相同。2.f(x)找到后,复合部分是等价无穷小。3.要满足作差的形式。如果是加
华为OD机试题本篇题目:明明的随机数题目输入描述输出描述:示例1输入输出说明代码编写思路最近更新的博客华为od2023|什么是华为od,od薪资待遇,od机试题清单华为OD机试真题大全,用Python解华为机试题|机试宝典【华为OD机试】全流程解析+经验分享,题型分享,防作弊指南华为o
我正在使用Mandrill的RubyAPIGem并使用以下简单的测试模板:testastic按照Heroku指南中的示例,我有以下Ruby代码:require'mandrill'm=Mandrill::API.newrendered=m.templates.render'test-template',[{:header=>'someheadertext',:main_section=>'Themaincontentblock',:footer=>'asdf'}]mail(:to=>"JaysonLane",:subject=>"TestEmail")do|format|format.h
所以这可能有点令人困惑,但请耐心等待。简而言之,我想遍历具有特定键值的所有属性,然后如果值不为空,则将它们插入到模板中。这是我的代码:属性:#===DefaultfileConfigurations#default['elasticsearch']['default']['ES_USER']=''default['elasticsearch']['default']['ES_GROUP']=''default['elasticsearch']['default']['ES_HEAP_SIZE']=''default['elasticsearch']['default']['MAX_OP
我有一个要在我的Rails3项目中使用的数组扩展方法。它应该住在哪里?我有一个应用程序/类,我最初把它放在(array_extensions.rb)中,在我的config/application.rb中我加载路径:config.autoload_paths+=%W(#{Rails.root}/应用程序/类)。但是,当我转到railsconsole时,未加载扩展。是否有一个预定义的位置可以放置我的Rails3扩展方法?或者,一种预先定义的方式来添加它们?我知道Rails有自己的数组扩展方法。我应该将我的添加到active_support/core_ext/array/conversion
我想编写一个ruby脚本来递归复制目录结构,但排除某些文件类型。因此,给定以下目录结构:folder1folder2file1.txtfile2.txtfile3.csfile4.htmlfolder2folder3file4.dll我想复制这个结构,但不包含.txt和.cs文件。因此,生成的目录结构应如下所示:folder1folder2file4.htmlfolder2folder3file4.dll 最佳答案 您可以使用查找模块。这是一个代码片段:require"find"ignored_extensions=[".cs"
这个问题有两个部分。在RubyProgrammingLanguage一书中,有一个使用模块扩展字符串对象和类的示例(第8.1.1节)。第一个问题。为什么如果您使用新方法扩展类,然后创建该类的对象/实例,则无法访问该方法?irb(main):001:0>moduleGreeter;defciao;"Ciao!";end;end=>nilirb(main):002:0>String.extend(Greeter)=>Stringirb(main):003:0>String.ciao=>"Ciao!"irb(main):004:0>x="foobar"=>"foobar"irb(main):