[骗分技巧——随机化Ⅰ]CodeChef-Milestones,CF364D-Ghd
文章目錄
- CodeChef-Milestones
- problem
- solution
- code
- CF364D-Ghd
- problem
- solution
- code
設(shè)隨機(jī)化一次的正確率為 ppp,一次的復(fù)雜度為 O(f(n))O(f(n))O(f(n))。則隨機(jī)的期望次數(shù) kkk:
k=∑i=1∞p(1?p)i?1i(1)(1?p)k=∑i=1∞p(1?p)ii=∑i=2∞p(1?p)i?1(i?1)(2)(1)?(2)?p?k=p+∑i=2∞p(1?p)i?1?k=1+∑i=2∞(1?p)i?1=∑i=0∞(1?p)ik=\sum_{i=1}^∞p(1-p)^{i-1}i\quad\quad\quad(1)\\\\ (1-p)k=\sum_{i=1}^∞p(1-p)^ii=\sum_{i=2}^∞p(1-p)^{i-1}(i-1)\quad (2)\\\\ (1)-(2)\Rightarrow p·k=p+\sum_{i=2}^∞p(1-p)^{i-1}\Rightarrow k=1+\sum_{i=2}^∞(1-p)^{i-1}=\sum_{i=0}^∞(1-p)^i k=i=1∑∞?p(1?p)i?1i(1)(1?p)k=i=1∑∞?p(1?p)ii=i=2∑∞?p(1?p)i?1(i?1)(2)(1)?(2)?p?k=p+i=2∑∞?p(1?p)i?1?k=1+i=2∑∞?(1?p)i?1=i=0∑∞?(1?p)i
由等比公式得: k=∑i=0∞(1?p)i=1?(1?p)∞1?(1?p)=1pk=\sum_{i=0}^∞(1-p)^i=\frac{1-(1-p)^∞}{1-(1-p)}=\frac{1}{p}k=∑i=0∞?(1?p)i=1?(1?p)1?(1?p)∞?=p1?。
綜上隨機(jī)算法求解的期望復(fù)雜度為 O(p?1f(n))O(p^{-1}f(n))O(p?1f(n))。
CodeChef-Milestones
problem
題目鏈接
solution
因?yàn)樽疃嘀挥衅邨l直線就可以覆蓋所有點(diǎn),可以推出 覆蓋點(diǎn)最多的直線至少覆蓋 ?n7?\lceil\frac n7\rceil?7n?? 個(gè)點(diǎn)。
也就是說,兩個(gè)點(diǎn)屬于同一直線的概率為 17\frac{1}{7}71?。
期望來說,777 次隨機(jī)化點(diǎn)就可以通過了,但是保險(xiǎn)起見,可以運(yùn)行 100010001000 次。
時(shí)間復(fù)雜度 O(Tnk)O(Tnk)O(Tnk),超了但是跑得很快》》o_o …
code
#include <bits/stdc++.h> using namespace std; #define maxn 10005 int T, n; double x[maxn], y[maxn];int main() {scanf( "%d", &T );while( T -- ) {scanf( "%d", &n );for( int i = 1;i <= n;i ++ ) scanf( "%lf %lf", &x[i], &y[i] );mt19937 wwl(time(0));uniform_int_distribution < int > range( 1, n );int ans = 0;for( int t = 1;t <= 1000;t ++ ) {int a = range( wwl ), b = range( wwl );int cnt = 0;if( x[a] == x[b] ) {for( int i = 1;i <= n;i ++ )if( x[i] == x[a] ) cnt ++;}else {cnt = 1;double k = ( y[a] - y[b] ) / ( x[a] - x[b] );for( int i = 1;i <= n;i ++ )if( x[i] != x[a] and ( y[i] - y[a] ) / ( x[i] - x[a] ) == k ) cnt ++;}ans = max( ans, cnt );}printf( "%d\n", ans );}return 0; }CF364D-Ghd
problem
題目鏈接
solution
貪心地,∣S′∣|S'|∣S′∣ 選出的子集大小應(yīng)該恰好為 ?n2?\lceil\frac{n}{2}\rceil?2n??,因?yàn)檫x擇的數(shù)越多,gcd?\gcdgcd 只會(huì)受到更多限制變小而不會(huì)變大。
那么每個(gè)數(shù)都是 12\frac 1 221? 的概率會(huì)屬于最后答案子集。
隨機(jī)化 101010 次,正確率 1?(1?12)101-(1-\frac 1 2)^{10}1?(1?21?)10 已經(jīng)很優(yōu)秀了。
隨機(jī)化出一個(gè)數(shù) axa_xax? 假設(shè)其屬于最后答案子集。
先求出 axa_xax? 的所有因子數(shù),最后的答案肯定是 axa_xax? 的因子。用桶 cntpcnt_pcntp? 記錄下來。
再求出與 aia_iai? 的 gcd?\gcdgcd,枚舉 gcd?\gcdgcd 的因子數(shù),找到因子所在的桶,cntp++cnt_p++cntp?++。
最后進(jìn)行桶的合并,如果桶 ppp 代表的因子是桶 qqq 代表的因子倍數(shù),則有 cntq+=cntpcnt_q+=cnt_pcntq?+=cntp?。
1e121e121e12 內(nèi)因子數(shù)最多的不超過 680068006800 個(gè)。
單次時(shí)間復(fù)雜度,假設(shè) δ(n)\delta(n)δ(n) 為 nnn 的因子個(gè)數(shù),O(ax+δ(n)2+nlog?n)O(\sqrt{a_x}+\delta(n)^2+n\log n)O(ax??+δ(n)2+nlogn)。
code
#include <bits/stdc++.h> using namespace std; #define int long long #define maxn 1000005 int n, ans, tot; int a[maxn], d[maxn], cnt[maxn];int gcd( int x, int y ) {if( ! y ) return x;else return gcd( y, x % y ); }void divide( int x ) {tot = 0;for( int i = 1;i * i <= x;i ++ )if( x % i == 0 ) {d[++ tot] = i;if( i * i != x ) d[++ tot] = x / i;}sort( d + 1, d + tot + 1 ); }void solve( int x ) {divide( x );for( int i = 1;i <= tot;i ++ ) cnt[i] = 0;for( int i = 1;i <= n;i ++ ) {int g = gcd( x, a[i] );int pos = lower_bound( d + 1, d + tot + 1, g ) - d;cnt[pos] ++;}for( int i = 1;i <= tot;i ++ )for( int j = i + 1;j <= tot;j ++ )if( d[j] % d[i] == 0 ) cnt[i] += cnt[j];for( int i = tot;i;i -- ) {if( d[i] <= ans ) break;if( cnt[i] >= ( n + 1 >> 1 ) ) ans = max( ans, d[i] );} }signed main() {scanf( "%lld", &n );for( int i = 1;i <= n;i ++ ) scanf( "%lld", &a[i] );mt19937 wwl(time(0));uniform_int_distribution < int > range( 1, n );for( int t = 1;t <= 10;t ++ ) {int x = range( wwl );solve( a[x] );}printf( "%lld\n", ans );return 0; }總結(jié)
以上是生活随笔為你收集整理的[骗分技巧——随机化Ⅰ]CodeChef-Milestones,CF364D-Ghd的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: win10系统winsxs文件夹该如何删
- 下一篇: Ubuntu 9.10 麦克风无声音解决