【BZOJ4872】分手是祝愿(期望DP)

题意:

B 君在玩一个游戏,这个游戏由 n 个灯和 n 个开关组成,给定这 n 个灯的初始状态,下标为
从 1 到 n 的正整数。每个灯有两个状态亮和灭,我们用 1 来表示这个灯是亮的,用 0 表示这个灯是灭的,游戏
的目标是使所有灯都灭掉。但是当操作第 i 个开关时,所有编号为 i 的约数(包括 1 和 i)的灯的状态都会被
改变,即从亮变成灭,或者是从灭变成亮。B 君发现这个游戏很难,于是想到了这样的一个策略,每次等概率随机
操作一个开关,直到所有灯都灭掉。这个策略需要的操作次数很多, B 君想到这样的一个优化。如果当前局面,
可以通过操作小于等于 k 个开关使所有灯都灭掉,那么他将不再随机,直接选择操作次数最小的操作方法(这个
策略显然小于等于 k 步)操作这些开关。B 君想知道按照这个策略(也就是先随机操作,最后小于等于 k 步,使
用操作次数最小的操作方法)的操作次数的期望。这个期望可能很大,但是 B 君发现这个期望乘以 n 的阶乘一定
是整数,所以他只需要知道这个整数对 100003 取模之后的结果。
1 ≤ n ≤ 100000, 0 ≤ k ≤ n;
 
思路:更正:下图中g[i]=((n-i)*g[i+1]+n)/i,官方题解谋财害命

 

我不是很了解最后一张图在说什么

 1 const mo=100003;
 2 var head,a:array[1..200000]of longint;
 3     vet,next:array[1..5000000]of longint;
 4     exf,f,g:array[0..200000]of int64;
 5     n,k1,i,j,t,e,v,tot:longint;
 6     s,ans:int64;
 7 
 8 procedure add(a,b:longint);
 9 begin
10  inc(tot);
11  next[tot]:=head[a];
12  vet[tot]:=b;
13  head[a]:=tot;
14 end;
15 
16 function mult(x,y:int64):int64;
17 begin
18  mult:=1;
19  while y>0 do
20  begin
21   if y and 1=1 then mult:=mult*x mod mo;
22   x:=x*x mod mo;
23   y:=y>>1;
24  end;
25 end;
26 
27 begin
28  assign(input,'bzoj4872.in'); reset(input);
29  assign(output,'bzoj4872.out'); rewrite(output);
30  readln(n,k1);
31  exf[0]:=1; exf[1]:=1;
32  for i:=2 to 100003 do exf[i]:=exf[mo mod i]*(mo-mo div i) mod mo;
33  for i:=1 to n do read(a[i]);
34  for i:=1 to n do
35   for j:=1 to n div i do
36   begin
37    t:=j*i;
38    add(t,i);
39   end;
40  for i:=n downto 1 do
41   if a[i]=1 then
42   begin
43    inc(s);
44    e:=head[i];
45    while e<>0 do
46    begin
47     v:=vet[e];
48     a[v]:=a[v] xor 1;
49     e:=next[e];
50    end;
51   end;
52  if s<=k1 then
53  begin
54   for i:=1 to n do s:=s*i mod mo;
55   writeln(s);
56   close(input);
57   close(output);
58   exit;
59  end;
60  g[n]:=1;
61  for i:=n-1 downto k1+1 do
62   g[i]:=(g[i+1]*(n-i) mod mo+n) mod mo*exf[i] mod mo;
63  for i:=1 to k1 do g[i]:=1;
64  for i:=0 to k1 do f[i]:=i;
65  for i:=k1+1 to n do f[i]:=(f[i-1]+g[i]) mod mo;
66  ans:=f[s];
67  for i:=1 to n do ans:=ans*i mod mo;
68  writeln(ans);
69  close(input);
70  close(output);
71 end.

 

 

 

posted on 2017-04-26 16:55  myx12345  阅读(211)  评论(0编辑  收藏  举报

导航