专家
公告
财富商城
电子网
旗下网站
首页
问题库
专栏
标签库
话题
专家
NEW
门户
发布
提问题
发文章
【带模的除法】poi2008 per
2019-04-13 21:16
发布
生成海报
站内文章
/
模拟电子
11142
0
1083
这道题的难点在于带模的除法,可恶的是模还不是质数,更可恶的是还没办法约分。。 看了标程才知道原来还可以这样做: 把取模的数进行分解质因数,对于你要乘或者要除以某一个数的时候,将这个数和模的gcd额外处理(其实直接把质因数的几次幂记下来就可以了),对于不是gcd的部分直接乘法逆元即可。 我是参考的标程的写法(ps:标程跑得非常慢),加略微的改进,感觉我应该不会写丑啊。。。但是交到h8oj上面去的时候果断被虐了。。估计是还有更优美的算法,那位路过的同学知道的告诉我哈。。
program per;{$inline+} var a,b,c:array[0..300000] of longint; d:array[0..10,-100..43] of int64; x,y,z,p:array[0..10] of int64; n,i,j,zt,ans,phm:longint; lt,mo,ch,pre,tmp:int64; function get:int64;inline;var i:longint; begin get:=lt;for i:=1 to zt do get:=get*p[i] mod mo end; function fmul(a:int64;b:longint):int64;inline; begin if (b=0)or(a=1) then exit(1); fmul:=sqr(fmul(a,b>>1))mod mo; if odd(b) then fmul:=fmul*a mod mo; end; function phi(x:longint):longint;inline;var i,k:longint; begin i:=1;phi:=1; while i*i<=x do begin inc(i);k:=1; while x mod i=0 do begin x:=x div i; k:=k*i; end; phi:=phi*(k-k div i); end; if x<>1 then phi:=phi*(x-1); end; procedure calc(a,b:int64);inline;var i:longint; begin for i:=1 to zt do while a mod x[i]=0 do begin a:=a div x[i]; inc(y[i],b); if b=1 then p[i]:=p[i]*x[i] mod mo else p[i]:=p[i]*z[i] mod mo; if y[i]<43 then p[i]:=d[i,y[i]]; end; if b=1 then lt:=lt*(a mod mo)mod mo else lt:=lt*fmul(a,phm) mod mo; end; begin readln(n,mo); tmp:=mo;lt:=1; for i:=1 to n do read(a[i]); for i:=2 to mo do if i*i>tmp then break else if tmp mod i=0 then begin inc(zt);x[zt]:=i; while tmp mod i=0 do tmp:=tmp div i; end; if tmp<>1 then begin inc(zt);x[zt]:=tmp; end; for i:=1 to zt do p[i]:=1; for i:=1 to zt do d[i,0]:=1; for i:=1 to zt do for j:=1 to 43 do d[i,j]:=d[i,j-1]*x[i] mod mo; for i:=1 to zt do begin tmp:=mo; while tmp mod x[i]=0 do tmp:=tmp div x[i]; z[i]:=fmul(x[i],phi(tmp)-1); end; phm:=phi(mo)-1; ans:=1;pre:=1; for i:=n downto 1 do begin inc(c[a[i]]); tmp:=0;j:=a[i]-1; while j>0 do begin inc(tmp,b[j]); dec(j,j and -j); end; j:=a[i]; while j<300001 do begin inc(b[j]); inc(j,j and -j); end; if n=i then ch:=1 else ch:=n-i; if tmp<>0 then ch:=ch*tmp; calc(ch,1); if pre=0 then calc(c[a[i]],-1) else calc(c[a[i]]*pre,-1); if tmp<>0 then ans:=(ans+get)mod mo; pre:=tmp; end; writeln(ans); end.
Ta的文章
更多
>>
为S3C6410,S5PC110等ARM平台快速构建一个Meego环境
0 个评论
【带模的除法】poi2008 per
0 个评论
热门文章
×
关闭
举报内容
检举类型
检举内容
检举用户
检举原因
广告推广
恶意灌水
回答内容与提问无关
抄袭答案
其他
检举说明(必填)
提交
关闭
×
打开微信“扫一扫”,打开网页后点击屏幕右上角分享按钮