文章目录
- CodeChef-Milestones
- problem
- solution
- code
- CF364D-Ghd
- problem
- solution
- code
设随机化一次的正确率为 ppp,一次的复杂度为 O(f(n))O(f(n))O(f(n))。则随机的期望次数 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。
综上随机算法求解的期望复杂度为 O(p−1f(n))O(p^{-1}f(n))O(p−1f(n))。
CodeChef-Milestones
problem
题目链接
solution
因为最多只有七条直线就可以覆盖所有点,可以推出 覆盖点最多的直线至少覆盖 ⌈n7⌉\lceil\frac n7\rceil⌈7n⌉ 个点。
也就是说,两个点属于同一直线的概率为 17\frac{1}{7}71。
期望来说,777 次随机化点就可以通过了,但是保险起见,可以运行 100010001000 次。
时间复杂度 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′∣ 选出的子集大小应该恰好为 ⌈n2⌉\lceil\frac{n}{2}\rceil⌈2n⌉,因为选择的数越多,gcd\gcdgcd 只会受到更多限制变小而不会变大。
那么每个数都是 12\frac 1 221 的概率会属于最后答案子集。
随机化 101010 次,正确率 1−(1−12)101-(1-\frac 1 2)^{10}1−(1−21)10 已经很优秀了。
随机化出一个数 axa_xax 假设其属于最后答案子集。
先求出 axa_xax 的所有因子数,最后的答案肯定是 axa_xax 的因子。用桶 cntpcnt_pcntp 记录下来。
再求出与 aia_iai 的 gcd\gcdgcd,枚举 gcd\gcdgcd 的因子数,找到因子所在的桶,cntp++cnt_p++cntp++。
最后进行桶的合并,如果桶 ppp 代表的因子是桶 qqq 代表的因子倍数,则有 cntq+=cntpcnt_q+=cnt_pcntq+=cntp。
1e121e121e12 内因子数最多的不超过 680068006800 个。
单次时间复杂度,假设 δ(n)\delta(n)δ(n) 为 nnn 的因子个数,O(ax+δ(n)2+nlogn)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;
}