NOIPの模拟_2016_7_19_t1_腐败
2016-07-19 21:14
323 查看
题目
input
第一行一个正整数n,表示序列长度
第二行n个正整数,为给出的序列A
Sample Input
3
6 4 12
Output
一个非负整数,为答案。
Sample Output
13824
Data Constraint
50%:n<=3000;
100%:n<=30000,A[i]<=10^7
题目の大意
这题并不需要2333(+10086);我比赛时の想法与吐槽
看到题先发动技能:奥义*蒙逼!蒙逼几分钟之后愉悦的想到了分解质因数,然后就愉悦的开始打了,打到一半发现这个模数十分神奇,似乎会爆int64!?于是有好的与同学交流了一番,回忆起了以前忘记的快速乘(其实我怎么看也都不快啊)。但是因为我比较垃圾,打的代码也十分捞,十分难调,两个小错误调到了下午四点555。大概思路
当前我们正在处理一个数x,那么我们先把ta分解成∏zs=1pkss的形式,然后把每一个小于sqrt(107)的数(也就是小于3162)放到一个f[i,j]中,f[i,j]表示在现在已经处理过的数中因子i的个数为j的个数,若有一个质数大于3162,容易发现这个质数在每一个数中指数最大为1,所以我们用一个g[i]来分开存储,这样就解决了空间的问题,然后我们分情况讨论:设x的质因子p有tt个,分两个部分计算答案
1:f[p,1—>tt],对于这一部分我们给答案*f[p,q]*l(l为pq)
2: f[p,tt+1—>cc[p]],对于这一部分答案*f[p,q]*l(l为ptt,设cc[p]=z,则cc[p]表示不大于107的最大的pz)
对于p<3162和p>3162当然是要分开处理的啦
快速乘
设cy=107,我们现在要求a*b的积。设a1=a mod cy;
a2=a div cy;
b1=b mod cy;
b2=b div cy;
那么a*b=(a2*cy+a1)*(b2*cy+b1),然后把ta拆开,把四项的答案都算出来然后相加就可以了,在计算的过程每做一步就mod一次就不会runtime error 了
贴代码(好长啊,还有好多调试时候的注释懒得删了2333~~)
CONST md=100000000009;cy=10000000; VAR T:ARRAY[0..10005,0..100]OF LONGINT; A:ARRAY[0..30005]OF LONGINT; B:ARRAY[0..10000005]OF LONGINT; Q,CC:ARRAY[0..10005]OF LONGINT; PP:ARRAY[0..1005,0..20005]OF int64; I,J,K,L,N,x,tt,ss:LONGINT; ANS,aa:INT64; procedure make_Prime_Number; var i,j:longint; k:int64; bz:array[0..10005]of boolean; begin fillchar(bz,sizeof(bz),false); for i:=2 to 3500 do if bz[i]=false then begin j:=i+i; while j<3500 do begin bz[j]:=true; inc(j,i); end; end; for i:=2 to 3162 do if bz[i]=false then begin inc(q[0]); q[q[0]]:=i; k:=i; j:=0; while k<30000*3162 do begin inc(j); k:=k*i; end; cc[i]:=j; end; end; PROCEDURE MAKE_PP; BEGIN FOR I:=2 TO 1000 DO BEGIN PP[I,1]:=I; FOR J:=2 TO 20000 DO PP[I,J]:=(PP[I,J-1]*I) MOD MD; END; END; function fate(x,y:int64):int64; var a1,a2,b1,b2,ls:int64; begin a1:=x mod cy; a2:=x div cy; b1:=y mod cy; b2:=y div cy; ls:=(((((a2*b2) mod md)*cy) mod md)*cy) mod md; ls:=ls+(((a2*b1) mod md)*cy) mod md; ls:=ls+(((a1*b2) mod md)*cy) mod md; ls:=(ls+a1*b1) mod md; exit(ls); // exit((x*y) mod md); end; BEGIN //assign(input,'1.in'); reset(input); READLN(N); FOR I:=1 TO N DO READ(A[I]); READLN; ANS:=A[1]; FOR I:=2 TO N DO ANS:=fate(ANS,A[I]); MAKE_Prime_Number; MAKE_PP; aa:=(cy*cy) mod md; for i:=1 to n do begin x:=a[i]; j:=1; while (q[j]<x) and (j<q[0]) do begin tt:=0; while x mod q[j]=0 do begin inc(tt); x:=x div q[j]; end; if tt>0 then begin l:=1; for k:=1 to tt do begin l:=(l*q[j]) mod md; if t[q[j],k]>0 then begin if l<=1000 then ans:=fate(ans,pp[l,t[q[j],k]]) else for ss:=1 to t[q[j],k] do ans:=fate(ans,l); end; end; for k:=tt+1 to cc[q[j]] do if t[q[j],k]>0 then begin if l<=1000 then ans:=fate(ans,pp[l,t[q[j],k]]) else for ss:=1 to t[q[j],k] do ans:=fate(ans,l); end; inc(t[q[j],tt]); end; inc(j); if sqrt(x)<q[j] then begin if x<3162 then begin if x=1 then continue; l:=x; if t[x,1]>0 then if l<=1000 then ans:=fate(ans,pp[l,t[x,1]]) else for ss:=1 to t[x,1] do ans:=fate(ans,l); inc(t[x,1]); for k:=2 to cc[x] do if t[x,k]>0 then begin if l<=1000 then ans:=fate(ans,pp[l,t[x,k]]) else for ss:=1 to t[x,k] do ans:=fate(ans,l); end; end; break; end; end; if x>3162 then begin for ss:=1 to b[x] do ans:=fate(ans,x); inc(b[x]); end; end; writeln(ans); // close(input); END.
相关文章推荐
- emmet精简笔记【笔记】
- 解密 Uber 数据团队的基础数据架构优化之路
- android MVP 架构思路
- 题目1070:今年的第几天?
- caffe的python接口学习(8):caffemodel中的参数及特征的抽取
- Windows下VC++显示UTF-8编码中文
- Python操作memecache
- unix:fork()函数进阶讲解
- jboss eap 6.2 ear包 下使用log4j日志
- Sublime Text插件之Emmet
- SharedPreferences缓存
- Linux VMnet Adapter无法启动的解决办法
- 使用url获取网络资源
- Centos7.2配置yum源
- Hadoop3.0新特性
- 【小松教你手游开发】【系统模块开发】根据上一个GameObject坐标生成的tips界面
- 文件路径和文件读取方
- 装逼利器批量unzip
- centos下espeak文本转语音的代码实现
- POJ 1721 CARDS <置换群>