生活随笔
收集整理的這篇文章主要介紹了
LOJ#2145. 「SHOI2017」分手是祝愿
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
LOJ#2145. 「SHOI2017」分手是祝愿
題目描述
Solution
首先有一個結論:
燈的狀態序列a1,a2...ana_1,a_2...a_na1?,a2?...an?唯一對應了一個最優操作序列b1,b2...bnb_1,b_2...b_nb1?,b2?...bn?。
因為編號最大的燈只能由開關自己來改變。
因此,就相當于你有一個操作序列bbb,當其中111的個數小于等于kkk時,你就會直接按最優解操作(即只會選最優操作序列中的111),否則隨機把操作序列中的一個位置010101反轉,求變為全000期望步數。
這一題有一個巧妙的dpdpdp。
令fif_ifi?表示從有iii個111走到有i?1i-1i?1個111所需要的期望步數。
根據定義與期望的線性性,顯然Ans=∑i≤cntfiAns=\sum_{i\leq cnt} f_iAns=∑i≤cnt?fi?,cntcntcnt表示操作序列有多少個111。
現在考慮fff怎么求。
顯然每一次操作,有n?in\frac{n-i}{n}nn?i?增加一個111,也有in\frac{i}{n}ni?的概率減少,所以有:
fi=infi+n?in(1+fi+fi+1)f_i=\frac{i}{n}f_i+\frac{n-i}{n}(1+f_i+f_{i+1}) fi?=ni?fi?+nn?i?(1+fi?+fi+1?)
表示要么減少一個111,要么增加一個111,再減少回來。
因此可以從fnf_nfn?直接遞推過來,時間復雜度O(n)O(n)O(n)。
#include <vector>
#include <list>
#include <map>
#include <set>
#include <deque>
#include <queue>
#include <stack>
#include <bitset>
#include <algorithm>
#include <functional>
#include <numeric>
#include <utility>
#include <sstream>
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <cctype>
#include <string>
#include <cstring>
#include <ctime>
#include <cassert>
#include <string.h>
#define MP(A,B) make_pair(A,B)
#define PB(A) push_back(A)
#define SIZE(A) ((int)A.size())
#define LEN(A) ((int)A.length())
#define FOR(i,a,b) for(int i=(a);i<(b);++i)
#define fi first
#define se secondusing namespace std
;template<typename T
>inline bool upmin(T
&x
,T y
) { return y
<x
?x
=y
,1:0; }
template<typename T
>inline bool upmax(T
&x
,T y
) { return x
<y
?x
=y
,1:0; }typedef long long ll
;
typedef unsigned long long ull
;
typedef long double lod
;
typedef pair
<int,int> PR
;
typedef vector
<int> VI
;const lod eps
=1e-11;
const lod pi
=acos(-1);
const int oo
=1<<30;
const ll loo
=1ll<<62;
const int mods
=100003;
const int MAXN
=600005;
const int INF
=0x3f3f3f3f;
inline int read()
{int f
=1,x
=0; char c
=getchar();while (c
<'0'||c
>'9') { if (c
=='-') f
=-1; c
=getchar(); }while (c
>='0'&&c
<='9') { x
=(x
<<3)+(x
<<1)+(c
^48); c
=getchar(); }return x
*f
;
}
int a
[MAXN
],f
[MAXN
],fac
[MAXN
],inv
[MAXN
];
inline int upd(int x
,int y
){ return x
+y
>=mods
?x
+y
-mods
:x
+y
; }
inline int quick_pow(int x
,int y
)
{int ret
=1;for (;y
;y
>>=1){if (y
&1) ret
=1ll*ret
*x
%mods
;x
=1ll*x
*x
%mods
;}return ret
;
}
void Init(int n
)
{fac
[0]=1;for (int i
=1;i
<=n
;i
++) fac
[i
]=1ll*fac
[i
-1]*i
%mods
;for (int i
=1;i
<=n
;i
++) inv
[i
]=quick_pow(i
,mods
-2);
}
int main()
{int n
=read(),k
=read(),cnt
=0;Init(n
);for (int i
=1;i
<=n
;i
++) a
[i
]=read();for (int i
=n
;i
>=1;i
--){if (!a
[i
]) continue;cnt
++;for (int j
=1;j
*j
<=i
;j
++)if (i
%j
==0) {a
[j
]^=1;if (j
*j
!=i
) a
[i
/j
]^=1;}
}
f
[n
]=1;for (int i
=1;i
<=k
;i
++) f
[i
]=1;for (int i
=n
-1;i
>k
;i
--) f
[i
]=upd(1ll*f
[i
+1]*(n
-i
)%mods
*inv
[i
]%mods
,1ll*n
*inv
[i
]%mods
);int ans
=0;for (int i
=1;i
<=cnt
;i
++) ans
=upd(ans
,f
[i
]);printf("%d\n",1ll*ans
*fac
[n
]%mods
);return 0;
}
總結
以上是生活随笔為你收集整理的LOJ#2145. 「SHOI2017」分手是祝愿的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。