好不容易坑来了传说中的USACO精选,近100题我要是能做完就哈哈哈哈了…继今天学并查集连番受挫之后,决定写一写基础题。
#0 负二进制 2014-01-10
其实是想到就会做,不想到就不会做的题,数学渣渣在此,赶紧承认自己看了解题0 0……其实我自己对于负数的mod不是很熟…如果考场上出这种东西自己开个exam.pas弄几个mod负数div负数不就摸索出来了么…
(其实我最开始的想法是,按正数除,除出来一个2^(2k-1)的就当成(-2)^2k+(-2)^(2k-1))
program tyvj_p1022; var a:array[1..10000] of integer; x,i,t:longint; begin readln(x); if x=0 then begin writeln(0); halt; end; t:=0; while x<>0 do begin inc(t); a[t]:=x mod (-2); if a[t]<0 then begin a[t]:=a[t]+2; x:=x-2; end; x:=x div (-2); end; for i:=t downto 1 do write(a[i]); end.
#1 数的幂次 2014-01-10
一开始还脑残在想这题是不是不用快速幂啊纯模拟啊…结果,写的快速幂+高精度,自己的机器都超时运作了…话说这题被坑了,我拿到的题目上写着答案不超过15000个字符的,结果我201个好久还以为是integer太小了,开成了longint,后来直接qword了… 后来数组开50000就over了…
不写不知道一写吓一跳噜,写快速幂+高精度要注意:(1)高精度自乘(本程序中采用ti数组)不要一脑残就以为是2在自己乘啊!(2)高精度a[i+j]:=a[i+j-1] div 10啊不要一脑残直接inc(a[i+j])…程序可优化的空间就是,写了两段高精度乘,其实可以弄成两个参数而不要再写一遍的…
program cruel1; var a,ti:array[0..50000] of qword; node:array[0..20] of boolean; n,p,t,i,tn,t0:longint; procedure work_self_times; var c:array[0..50000] of qword; i,j,t:longint; begin fillchar(c,sizeof(c),0); for i:=1 to ti[0] do for j:=1 to ti[0] do begin c[i+j-1]:=c[i+j-1]+ti[i]*ti[j]; if c[i+j-1]>9 then begin c[i+j]:=c[i+j]+c[i+j-1] div 10; c[i+j-1]:=c[i+j-1] mod 10; end; end; t:=2*ti[0]; while c[t]=0 do dec(t); c[0]:=t; ti:=c; end; procedure times; var c:array[0..50000] of qword; i,j,t:longint; begin fillchar(c,sizeof(c),0); for i:=1 to a[0] do for j:=1 to ti[0] do begin c[i+j-1]:=c[i+j-1]+a[i]*ti[j]; if c[i+j-1]>9 then begin c[i+j]:=c[i+j]+c[i+j-1] div 10; c[i+j-1]:=c[i+j-1] mod 10; end; end; t:=2*ti[0]; while c[t]=0 do dec(t); c[0]:=t; a:=c; end; begin readln(n,p); t:=1; while p<>0 do begin if p mod 2=1 then node[t]:=true; p:=p div 2; inc(t); end; fillchar(a,sizeof(a),0); a[1]:=1; a[0]:=1; fillchar(ti,sizeof(ti),0); t0:=1;tn:=n; while tn<>0 do begin ti[t0]:=tn mod 10; tn:=tn div 10; inc(t0); end; ti[0]:=t0-1; for i:=1 to t do begin if node[i]=true then times; work_self_times; end; t:=15000; while a[t]=0 do dec(t); for i:=t downto 1 do write(a[i]); end.
#2 分数变小数 2014-01-11
又脑残去搜题解了,结果看到很多大神的博客都说这题神坑,我还以为这题有多么的奇葩… 其实就是除法啦,第一次出错后还莫名其妙想了个要写链表的方法…(那方法其实是错的,但是话说上一次写链表是不知道多少年前了,要练习一下。)
x是商,x0是余数(多余的,可以不用),mark标记余数是否出现过。output1用于无循环的小数的输出,output2用于循环小数的输出。
其实有点虚,目测了一下答案是对的,但是数据7和8实在太长了…
program usaco_3; var n,d,z,t,i:longint; x,x0:array[0..200000] of longint; mark:array[0..100000] of longint; procedure output1; var i:longint; begin for i:=0 to t do write(x[i]); halt; end; procedure output2(l,r:longint); var i:longint; begin for i:=1 to t do begin if i=l+1 then write('('); write(x[i]); if i=r then write(')'); end; halt; end; begin readln(n,d); z:=n div d; n:=n mod d; write(z,'.'); if n=0 then begin write('0'); halt; end; t:=0; for i:=1 to 100000 do mark[i]:=-1; mark[n]:=0; while true do begin inc(t); x0[t]:=n; n:=n*10; x[t]:=n div d; n:=n mod d; if n=0 then output1; if (mark[n]<>-1) then output2(mark[n],t) else mark[n]:=t; end; end.
#3 丑数 2014-01-12
之前有两个程序是失败的,两个都是枚举list中的数据而不是p中的素数,导致慢的要死,要知道k的范围是[1,100],n的范围是[1,100000]…第二个稍微加了个小优化,用p0记录以免重复乘。然后默默去看题解…(啊啊啊你怎么能这么不独立呢!)于是开始枚举素数,用p0记录。但是第12个数据点的n=100000貌似还是很慢,这题目前没找到到oj可以测评(没去找…),去网上拉了个题解复制下来看看貌似第12点都超级慢,那就先搁着吧,等我USACO的training做到Chapter 3了去提交一下就知道了…
BTW快排可以不用写,我拿到的翻译里面没写输入的时候是有序的所以我自作多情地写了一个… T T
最终的:
program usaco_3; var k,n,i,j,l,t,t0:dword; p,p0:array[1..100] of longint; list:array[0..100000] of dword; procedure qsort(l,r:longint); var i,j,mid,t:longint; begin i:=l;j:=r;mid:=p[(l+r) div 2]; repeat while p[i]<mid do inc(i); while p[j]>mid do dec(j); if i<=j then begin t:=p[i];p[i]:=p[j];p[j]:=t; inc(i);dec(j); end; until i>j; if i<r then qsort(i,r); if j>l then qsort(l,j); end; begin readln(k,n); for i:=1 to k do read(p[i]); qsort(1,k); list[1]:=1; for i:=2 to n+1 do begin t:=maxlongint; for j:=1 to k do begin while p[j]*list[p0[j]]<=list[i-1] do inc(p0[j]); if p[j]*list[p0[j]]<t then t:=p[j]*list[p0[j]]; end; list[i]:=t; end; writeln(list[n+1]); end.
前两个失败的:
program usaco_3; var k,n,i,j,t,t0:longint; p:array[1..100] of longint; list:array[1..100000] of longint; procedure qsort(l,r:longint); var i,j,mid,t:longint; begin i:=l;j:=r;mid:=p[(l+r) div 2]; repeat while p[i]<mid do inc(i); while p[j]>mid do dec(j); if i<=j then begin t:=p[i];p[i]:=p[j];p[j]:=t; inc(i);dec(j); end; until i>j; if i<r then qsort(i,r); if j>l then qsort(l,j); end; function search(start,xi:longint):longint; var t,i:longint; begin for i:=1 to k do if start*p[i]>xi then begin t:=start*p[i]; exit(t); end; end; begin readln(k,n); for i:=1 to k do read(p[i]); qsort(1,k); list[1]:=1; for i:=2 to n+1 do begin t:=maxlongint; for j:=1 to i-1 do begin t0:=search(list[j],list[i-1]); if t0<t then t:=t0; end; list[i]:=t; end; writeln(list[n+1]); end.
program usaco_3; var k,n,i,j,t,t0:longint; p:array[1..100] of longint; list,p0:array[1..100000] of longint; procedure qsort(l,r:longint); var i,j,mid,t:longint; begin i:=l;j:=r;mid:=p[(l+r) div 2]; repeat while p[i]<mid do inc(i); while p[j]>mid do dec(j); if i<=j then begin t:=p[i];p[i]:=p[j];p[j]:=t; inc(i);dec(j); end; until i>j; if i<r then qsort(i,r); if j>l then qsort(l,j); end; function search(start,xi:longint):longint; var t,i:longint; begin if p0[start]>xi then exit(p0[start]); for i:=1 to k do if list[start]*p[i]>xi then begin t:=list[start]*p[i]; p0[start]:=t; exit(t); end; end; begin readln(k,n); for i:=1 to k do read(p[i]); qsort(1,k); list[1]:=1; for i:=2 to n+1 do begin t:=maxlongint; for j:=1 to i-1 do begin t0:=search(j,list[i-1]); if t0<t then t:=t0; end; list[i]:=t; end; writeln(list[n+1]); end.