【Test】[20111011][数论+记忆化搜索+枚举(Heap优化)+SPFA]

【闲话】

成绩:

第一题(Count):AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

第二题(Length):AAATTTTTTT

第三题(Station):AAAAAAAAAAAAAAAAAAAA

第四题(Party):AAAAAAAAAA

第三题的满分是骗的,O(n2)过了全点,真正的解法应该是O(nlogn)的。

第二题确实没写过类似的题。

【题目】

数数(Count)

【问题描述】

给定n,m,k都是小于等于10001的正整数,输出给定的n个数中,其m次幂能被k整除的数的个数。

【输入格式】

有两行组成,第一行是三个整数n,m,k

第二行是n个正整数 都不超过10001

【输出格式】

输出满足条件的数的个数

【样例输入】count.in

3 2 50

9 10 11

【样例输出】count.out

1

【解析】

两种解法。

1.快速模取幂,效率O(nlogm)。不阐述…

2.分解质因数,效率O(n*25)。看程序吧…

最长链

【问题描述】

给定一棵有N个节点的树,求每个节点到其他节点的最大距离

【输入格式】

输入第一行是一个自然数 N (N<=10000), 接下来 (N-1) 行描述:

第i行包含两个自然数 , 表示编号为i的节点连接到的节点编号和这条网线的长度..距离总长不会超过10^9. 每行中的两个数字用空格隔开.

【输出格式】

输出包含N行. 第i行表示对于离编号为i的节点最远的节点与该节点的距离Si(1<=i<=N).

【样例输入】length.in

3

1 1

1 2

【样例输出】length.out

2

3

3

【数据范围】

30% N<=100

100%N<=10000

【解析】

应用树形动归(记忆花搜索)的方法。

传送门:_______。

水站

【问题描述】

已知有一个N 层的水站 :

Wi表示未操作之前第i层的已有水量;

Li 表示第i个水站能够维持或者储存的水的重量;

Pi 表示在第i层进行减压放水操作所需的费用.

被压减放水层所储存的所有水都将流向下一层.

如果第 i层的水量比Li大,则这一层也会(自动)减压(不需要任何费用).

现在想要使最后一层减压(第N级) ,求最少的花费.

这个任务现在交给了你。

【输入格式】

每个输入的第一行包含一个自然数N (1<=N<=15000).

接下来N行每行包含 3 个数 Wi, Li, Pi (0<=Wi,Li,Pi<=15000).

【输出格式】

第一行输出所需的最小费用

第二行若干个整数,从小到大输出必须减压的层的编号。

【样例输入】station.in


1000 1000 1 
0 1000 2 
2 10 100

【样例输出】station.out

3

1 2

Hint:给第一层和第二层减压

【数据范围】

30% N<=5000

100%N<=15000

【题意分析】

令Si=W1+W2+…+Wi(特别的S0=0)。

不妨设恐怖分子炸毁的第高层是第p层(第一层是最高层,第N层是最底层)。

因为恐怖分子的目标是毁灭第N层,所以水必须从第p层一直泻下去。如果存在一个i,满足Wp+Wp+1+…+Wi-1+Wi<=Li,也就是说前面几层的水全部泄下来也无法把第i层自动冲毁,那么就必须要使用炸药把它炸开了。

所以恐怖分子需要炸毁的层的集合就是Bomb[p]={p}∪{i |i>p Si-Sp-1<=Li}

令Qi=Si-Li,那么:

Bomb[p]={p}∪{i |i>p Qi<=Sp-1}

我们枚举p,然后看哪些层需要炸毁。这样就得到了一个O(n2)的算法。

【设计算法】

n<=15000,O(n2)的算法效率太低。

注意到Sp是随着p的增加而递增的,观察两个集合:

Bomb[p]={p}∪{i |i>p Qi<=Sp-1}

Bomb[p-1]={p-1}∪{i |i>p-1 Qi<=Sp-2}

因为Sp-2<=Sp-1,所以{i |i>p-1 Qi<=Sp-2}clip_image002Bomb[p]。

也就是说,Bomb[p-1]是在Bomb[p]的基础上,通过以下操作得到的:

1.删除所有的i∈Bomb[p],Qi>Sp-2

2.添加p-1。

针对这两种操作,我们可以使用大根堆(Heap)。从大到小枚举p,对于每一个p,执行:

Step1. 如果堆的根i满足Qi >Sp-2,那么删除根;否则转Step3。

Step2. 转Step1。

Step3. 添加p-1。

每层至多进堆一次、出堆一次,所以总的时间复杂度是O(nlogn)。对于n<=15000的范围完全能够胜任了。

聚会

【问题描述】

小S想要从某地出发去同学k的家中参加一个party,但要有去有回。他想让所用的时间尽量的短。但他又想知道从不同的点出发,来回的最短时间中最长的时间是多少,

这个任务就交给了你。

【输入格式】

第一行三个正整数n,m,k(n是节点个数,m是有向边的条数,k是参加聚会的地点编号)( 1 ≤ N ≤ 1000 ,1 ≤ M ≤ 100,000)

第二行..m+1行每行3个整数x,y,w 代表从x到y需要花w的时间(1 ≤ w≤ 100)

【输出格式】

输出从不同的节点出发的最短时间中最长的时间。

【样例输入】party.in

4 8 2

1 2 4

1 3 2

1 4 7

2 1 1

2 3 5

3 1 2

3 4 4

4 2 3

【样例输出】party.out

10

【解析】

对每一个点两遍SPFA,注意返回值如果为$7F则为不连通,此时不能更新ans。

【Code】

第一题:

  1: Program Count(input,output);
  2:   const List:array[1..168]of longint=
  3: (
  4: 2,3,5,7,11,13,17,19,23,29,
  5: 31,37,41,43,47,53,59,61,67,71,
  6: 73,79,83,89,97,101,103,107,109,113,
  7: 127,131,137,139,149,151,157,163,167,173,
  8: 179,181,191,193,197,199,211,223,227,229,
  9: 233,239,241,251,257,263,269,271,277,281,
 10: 283,293,307,311,313,317,331,337,347,349,
 11: 353,359,367,373,379,383,389,397,401,409,
 12: 419,421,431,433,439,443,449,457,461,463,
 13: 467,479,487,491,499,503,509,521,523,541,
 14: 547,557,563,569,571,577,587,593,599,601,
 15: 607,613,617,619,631,641,643,647,653,659,
 16: 661,673,677,683,691,701,709,719,727,733,
 17: 739,743,751,757,761,769,773,787,797,809,
 18: 811,821,823,827,829,839,853,857,859,863,
 19: 877,881,883,887,907,911,919,929,937,941,
 20: 947,953,967,971,977,983,991,997
 21: );
 22:   var Std,Test:array[1..168]of longint;
 23:       n,m,k,a,ans,tmp,i,j:longint;
 24:       Flag:boolean;
 25:   begin
 26:     assign(input,'count.in');reset(input);
 27:     assign(output,'count.out');rewrite(output);
 28:     readln(n,m,k);ans:=0;Fillchar(Std,sizeof(Std),0);
 29:     for i:=1 to 168 do
 30:       if k mod List[i]=0 then
 31:         begin
 32:           tmp:=0;
 33:           while k mod List[i]=0 do
 34:             begin
 35:               inc(tmp);
 36:               k:=k div List[i];
 37:             end;
 38:           Std[i]:=tmp;
 39:         end;
 40:     for i:=1 to n do
 41:       begin
 42:         read(a);Flag:=true;Fillchar(Test,sizeof(Test),0);
 43:         for j:=1 to 168 do
 44:           begin
 45:             if a mod List[j]=0 then Test[j]:=m;
 46:             if Test[j]<Std[j] then begin Flag:=false;break;end;
 47:           end;
 48:         if flag then inc(ans);
 49:       end;
 50:     writeln(ans);
 51:     close(input);
 52:     close(output);
 53:   end.
 54: 

第二题:

  1: Program length(input,output);
  2: type
  3:   edge=record
  4:     x,w,next:longint;
  5:   end;
  6: var
  7:   e,e2:array[0..200000]of edge;
  8:   k,k2:array[0..10000]of longint;
  9:   fa:array[0..10000]of longint;
 10:   w:array[0..10000]of longint;
 11:   tot,tot2,i,j,n,x,y:longint;
 12:   v:array[0..10000]of boolean;
 13:   f:array[0..10000,0..2]of longint;
 14: function max(a,b:longint):longint;
 15:   begin
 16:     if (a>b) then exit(a) else exit(b);
 17:   end;
 18: procedure add2(a,b,c:longint);
 19:   begin
 20:     inc(tot2);
 21:     e2[tot2].x:=b;
 22:     e2[tot2].w:=c;
 23:     e2[tot2].next:=k2[a];
 24:     k2[a]:=tot2;
 25:   end;
 26: procedure add(a,b,c:longint);
 27:   begin
 28:     inc(tot);
 29:     e[tot].x:=b;
 30:     e[tot].w:=c;
 31:     e[tot].next:=k[a];
 32:     k[a]:=tot;
 33:   end;
 34: procedure build(x:longint);
 35:   var
 36:     t:longint;
 37:   begin
 38:     v[x]:=true;
 39:     t:=k2[x];
 40:     while (t<>0) do
 41:       begin
 42:         if (not v[e2[t].x]) then
 43:           begin
 44:             fa[e2[t].x]:=x;
 45:             w[e2[t].x]:=e2[t].w;
 46:             add(x,e2[t].x,e2[t].w);
 47:             build(e2[t].x);
 48:           end;
 49:         t:=e2[t].next;
 50:       end;
 51:   end;
 52: procedure dp_down(x:longint);
 53:   var
 54:     t:longint;
 55:   begin
 56:     t:=k[x];
 57:     while (t<>0) do
 58:       begin
 59:         dp_down(e[t].x);
 60:         if (f[e[t].x][1]+e[t].w>f[x][1]) then
 61:           begin
 62:             f[x][2]:=f[x][1];
 63:             f[x][1]:=f[e[t].x][1]+e[t].w;
 64:           end
 65:           else
 66:         if (f[e[t].x][1]+e[t].w>f[x][2]) then
 67:           begin
 68:             f[x][2]:=f[e[t].x][1]+e[t].w;
 69:           end;
 70:         t:=e[t].next;
 71:       end;
 72:   end;
 73: procedure dp_up(x:longint);
 74:   var
 75:     t:longint;
 76:   begin
 77:     if (fa[x]<>0) then
 78:       begin
 79:         if (f[fa[x]][1]=f[x][1]+w[x]) then
 80:           f[x][0]:=max(f[fa[x]][2],f[fa[x]][0])+w[x]
 81:         else f[x][0]:=max(f[fa[x]][1],f[fa[x]][0])+w[x];
 82:       end;
 83:     t:=k[x];
 84:     while (t<>0) do
 85:       begin
 86:         dp_up(e[t].x);
 87:         t:=e[t].next;
 88:       end;
 89:   end;
 90: begin
 91:   assign(input,'length.in');reset(input);
 92:   assign(output,'length.out');rewrite(output);
 93:   readln(n);
 94:   for i:=2 to n do
 95:     begin
 96:       readln(x,y);
 97:       add2(i,x,y);
 98:       add2(x,i,y);
 99:     end;
100:   build(1);
101:   dp_down(1);
102:   dp_up(1);
103:   for i:=1 to n do
104:     begin
105:       writeln(max(f[i][0],f[i][1]));
106:     end;
107:   close(input);
108:   close(output);
109: end.

第三题:

  1: Program Station(input,output);
  2:   var sum,now,most,cost:array[1..15000]of longint;
  3:       n,i,ansmoney,ans,money,j:longint;
  4:   begin
  5:     assign(input,'Station.in');reset(input);
  6:     assign(output,'Station.out');rewrite(output);
  7:     readln(n);
  8:     for i:=1 to n do
  9:       begin
 10:         readln(now[i],most[i],cost[i]);
 11:         sum[i]:=sum[i-1]+now[i];
 12:       end;
 13:     ansmoney:=19940805;
 14:     for i:=1 to n do
 15:       begin
 16:         Money:=cost[i];
 17:         for j:=i+1 to n do
 18:           begin
 19:             if(sum[j]-sum[i-1]<=most[j])then inc(money,cost[j]);
 20:             if money>ansmoney then break;
 21:           end;
 22:         if money<ansmoney then
 23:           begin
 24:             ansmoney:=money;
 25:             ans:=i;
 26:           end;
 27:       end;
 28:     writeln(ansmoney);write(ans,' ');
 29:     for i:=ans+1 to n do
 30:       if(sum[i]-sum[ans-1]<=most[i])then
 31:         write(i,' ');
 32:     close(input);
 33:     close(output);
 34:   end.

这个Code是O(n^2)的,但是她出人意料的Ac了。

  1: program dsqwwe;
  2:   type
  3:     tt=record
  4:      x,y:longint;
  5:     end;
  6:   var
  7:     a:array[1..30005] of tt;
  8:     p,l,w,sum:array[0..30005] of longint;
  9:     done:boolean;
 10:     i,n,tot,cost,min,k:longint;
 11:   procedure up(i:longint);
 12:    var
 13:      t:tt;
 14:    begin
 15:      done:=false;
 16:      if i=1 then exit;
 17:      repeat
 18:        if a[i].x>a[i div 2].x then
 19:         begin
 20:           t:=a[i]; a[i]:=a[i div 2]; a[i div 2]:=t;
 21:         end
 22:        else done:=true;
 23:        i:=i div 2;
 24:      until (i=1) or done;
 25:    end;
 26:   procedure down(i:longint);
 27:     var
 28:       t:tt;
 29:     begin
 30:       done:=false;
 31:       if i*2>tot then exit;
 32:       repeat
 33:         i:=i*2;
 34:         if (i+1<=tot) and (a[i+1].x>a[i].x) then inc(i);
 35:         if a[i div 2].x<a[i].x then
 36:          begin
 37:            t:=a[i div 2]; a[i div 2]:=a[i]; a[i]:=t;
 38:          end
 39:         else done:=true;
 40:       until (2*i>tot) or done;
 41:     end;
 42:   procedure delete;
 43:     begin
 44:       cost:=cost-a[1].y;
 45:       a[1].x:=-1000000000;
 46:       down(1);
 47:     end;
 48:   begin
 49:     assign(input,'station.in');reset(input);
 50:     assign(output,'station.out');rewrite(output);
 51:     readln(n);
 52:     for i:=1 to n do
 53:      begin
 54:        readln(w[i],l[i],p[i]);
 55:        sum[i]:=sum[i-1]+w[i];
 56:      end;
 57:     tot:=1;
 58:     a[1].x:=sum[n]-l[n];
 59:     a[1].y:=p[n];
 60:     if w[n]>l[n] then a[1].y:=0;
 61:     cost:=a[1].y;
 62:     min:=cost;
 63:     for i:=n-1 downto 1 do
 64:      begin
 65:        while (a[1].x>sum[i-1]) do delete;
 66:        inc(tot);
 67:        a[tot].x:=sum[i]-l[i];
 68:        a[tot].y:=p[i];
 69:        if w[i]>l[i] then begin
 70:                             a[tot].y:=0;
 71:                           end
 72:        else cost:=cost+p[i];
 73:        up(tot);
 74:        if cost<min then
 75:          begin
 76:            min:=cost;
 77:            k:=i;
 78:          end;
 79:      end;
 80:     writeln(min);
 81:     write(k,' ');
 82:     for i:=k+1 to n do
 83:      if sum[i]-sum[k-1]<=l[i] then
 84:       write(i,' ');
 85:     close(input);
 86:     close(output);
 87:   end.
 88: 

兆哥的,Ac标准程序

第四题:

  1: Program Party(input,output);
  2:   type point=^node;
  3:        node=record
  4:          data,weight:longint;
  5:          next:point;
  6:        end;
  7:   var que:array[1..10000]of longint;
  8:       map:array[1..10000]of point;
  9:       vis:array[1..10000]of boolean;
 10:       dist:array[1..10000]of longint;
 11:       head,tail,quehead,n,m,k,ans,d,i,x,y,c:longint;
 12:       p,edge:point;
 13:   Function SPFA(st,ed:longint):longint;
 14:     begin
 15:       fillchar(que,sizeof(que),0);
 16:       fillchar(vis,sizeof(vis),false);
 17:       fillchar(dist,sizeof(dist),$7F);
 18:       dist[st]:=0;head:=0;tail:=1;que[tail]:=st;
 19:       while head<tail do
 20:         begin
 21:           inc(head);
 22:           quehead:=que[head];vis[quehead]:=false;edge:=map[quehead];
 23:           while edge<>nil do
 24:             begin
 25:               if dist[quehead]+edge^.weight<dist[edge^.data] then
 26:                 begin
 27:                   dist[edge^.data]:=dist[quehead]+edge^.weight;
 28:                   if not(vis[edge^.data]) then
 29:                     begin
 30:                       inc(tail);
 31:                       que[tail]:=edge^.data;
 32:                       vis[edge^.data]:=true;
 33:                     end;
 34:                 end;
 35:               edge:=edge^.next;
 36:             end;
 37:         end;
 38:       exit(dist[ed]);
 39:     end;
 40:   begin
 41:     assign(input,'Party.in');reset(input);
 42:     assign(output,'Party.out');rewrite(output);
 43:     readln(n,m,k);
 44:     for i:=1 to m do
 45:       begin
 46:         readln(x,y,c);
 47:         new(p);p^.data:=y;p^.weight:=c;p^.next:=map[x];map[x]:=p;
 48:       end;
 49:     ans:=-19940805;
 50:     for i:=1 to n do
 51:       begin
 52:         d:=SPFA(i,k)+SPFA(k,i);
 53:         if(d>ans)and(d<19940805)then ans:=d;
 54:       end;
 55:     writeln(ans);
 56:     close(input);
 57:     close(output);
 58:   end.
posted @ 2011-10-11 14:40  Loongint  阅读(380)  评论(0编辑  收藏  举报