2023杭电多校第五场 - 1 7 12

比赛地址:传送门
赛时过了 4 题,今天这场把这辈子的 TLE 都吃了一遍。。。
后期直接坐牢,还得加练啊!
1001 计算几何 点到线段的距离
1007 二项式定理求期望
1012 求组合数


1001 Typhoon

题意
给你一条折线路径,再给你一系列点,问你这些点到该折线的最短距离?

思路
计算几何基础题
本题模拟即可,对于每个点遍历所有折线,取距离最小值
\(O(mn)\) 即可通过
没有计算几何板子怎么办? 现在就开始准备!!!

代码

//>>>Qiansui
#include<bits/stdc++.h>
#define ll long long
#define ull unsigned long long
#define mem(x,y) memset(x, y, sizeof(x))
#define debug(x) cout << #x << " = " << x << '\n'
#define debug2(x,y) cout << #x << " = " << x << " " << #y << " = "<< y << '\n'
//#define int long long

using namespace std;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef pair<ull, ull> pull;
typedef pair<double, double> pdd;
/*

*/
const int maxm = 2e5 + 5, inf = 0x3f3f3f3f, mod = 998244353;

const double pi = acos(-1.0);
const double eps = 1e-8;

int sgn(double x){//判断x的大小
	if(fabs(x)<eps) return 0;
	else return x<0?-1:1;
}

int dcmp(double x,double y){//比较两个浮点数
	return sgn(x - y);
}

inline int dcmp(double a){
	return a<-eps?-1:(a>eps?1:0); //处理精度
}

struct Point{  
	double x,y;
	Point(){}
	Point(double x,double y):x(x),y(y){}

	Point operator + (const Point& B){return Point(x+B.x,y+B.y);}
	Point operator - (const Point& B){return Point(x-B.x,y-B.y);}
};

typedef Point Vector;

double Dot(const Vector& A, const Vector& B){ return A.x*B.x + A.y*B.y; }
double Cross(const Vector& A, const Vector& B){return A.x*B.y - A.y*B.x;}
double Distance(Point A,Point B){ return sqrt((A.x-B.x)*(A.x-B.x) + (A.y-B.y)*(A.y-B.y)); }

struct Line{
	Point p1,p2;                  //直线上的两个点构成Line
	Line(){}
	Line(Point p1,Point p2):p1(p1),p2(p2){}
};

typedef Line Segment;

double Dis_point_line(Point &p, Line &v){
	return fabs(Cross(p-v.p1,v.p2-v.p1))/Distance(v.p1,v.p2);
}

double Dis_point_seg(Point &p, Segment &v){
	if(sgn(Dot(p- v.p1,v.p2-v.p1)) < 0 || sgn(Dot(p- v.p2,v.p1-v.p2)) < 0)
		return min(Distance(p,v.p1),Distance(p,v.p2));
	return Dis_point_line(p,v);           //点的投影在线段上
}

void solve(){
	int n, m;
	cin >> m >> n;
	Point a, b;
	vector<Line> l;
	for(int i = 0; i < m; ++ i){
		cin >> a.x >> a.y;
		if(i){
			l.push_back(Line(a,b));
			b = a;
		}else{
			b = a;
		}
	}
	int len = l.size();
	for(int i = 0; i < n; ++ i){
		cin >> a.x >> a.y;
		double ans;
		for(int j = 0; j < len; ++ j){
			if(j){
				double t = Dis_point_seg(a, l[j]);
				if(dcmp(ans, t) == 1) ans = t;
			}else ans = Dis_point_seg(a, l[j]);
		}
		cout << fixed << setprecision(4) << ans << '\n';
	}
	return ;
}

signed main(){
	ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
	int _ = 1;
	// cin >> _;
	while(_ --){
		solve();
	}
	return 0;
}


1007 Expectation (Easy Version)

题意
你可以进行游戏 n 轮,每次游戏你赢的概率为 $\frac{a}{b} $。每次你赢的时候,你将会获得 $k^m $分, k 为你目前一共赢的次数。问你最后分数的期望取模 998244353

思路
由题可得 \(P(X = i) = C_{n}^{i} · p^i · (1 - p)^i\)
\(ans = \displaystyle \sum_{i = 1}^{n} P(X = i) · \displaystyle \sum_{j = 1}^{i}{j^m}\)
记得取模即可
赛时TLE....................... 优化是将 $p^i $ 和 $(1 - p)^{n - i} $ 提取出来,每次遍历 k 的时候再单独成,而不用 qpow 来求,这样就不 T 了

代码

//>>>Qiansui
#include<bits/stdc++.h>
#define ll long long
#define ull unsigned long long
#define mem(x,y) memset(x, y, sizeof(x))
#define debug(x) cout << #x << " = " << x << '\n'
#define debug2(x,y) cout << #x << " = " << x << " " << #y << " = "<< y << '\n'
//#define int long long

using namespace std;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef pair<ull, ull> pull;
typedef pair<double, double> pdd;
/*

*/
const int maxm = 2e5 + 5, inf = 0x3f3f3f3f;

const int N = 1e6 + 10, mod = 998244353;
ll fact[N], finv[N];
ll qpow(ll a, ll x){//带模快速幂
	ll res = 1;
	while(x){
		if(x & 1) res = res * a % mod;
		x >>= 1;
		a = a * a % mod;
	}
	return res;
}

void pre(){//线性预处理
	fact[0] = 1;
	for(int i = 1; i < N; ++ i){
		fact[i] = fact[i - 1] * i % mod;
	}
	finv[0] = 1;
	finv[N - 1] = qpow(fact[N - 1], mod - 2);
	for(int i = N - 2; i > 0; -- i)
		finv[i] = finv[i + 1] * (i + 1) % mod;
	return ;
}

ll C(int a, int b){//求取组合数
	if(a < 0 || b < 0) return 1;
	return fact[a] * finv[b] % mod * finv[a - b] % mod;
}

void solve(){
	int n, m, a, b;
	cin >> n >> m >> a >> b;
	ll invb = qpow(b, mod - 2), ans = 0, temp, sum = 0;
	ll p = a * invb % mod, q = (b - a) * invb % mod;
	ll pp = 1, qq = qpow(q, n), invq = qpow(q, mod - 2);
	for(int i = 1; i <= n; ++ i){
		sum = (sum + qpow(i, m)) % mod;
		pp = pp * p % mod;
		qq = qq * invq % mod;
		temp = C(n, i) * pp % mod * qq % mod * sum % mod;
		ans = (ans + temp) % mod;
	}
	cout << ans << '\n';
	return ;
}

signed main(){
	pre();
	ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
	int _ = 1;
	cin >> _;
	while(_ --){
		solve();
	}
	return 0;
}


1012 Counting Stars

题意
给你一个 n 个顶点,m 条边的无向图,问你该图中存在的 k-star 图在 \(k \in [2, n - 1]\) 范围的个数取模 $10^9 + 7 $ 后的异或和?

思路
暴力,对于每个顶点依次枚举其为中心,在其所连边中选 k 条边即为 k-star 图,之后求组合数统计每个 k 的个数,最后求异或和即可
赛时一直TLE....

代码

//>>>Qiansui
#include<bits/stdc++.h>
#define ll long long
#define ull unsigned long long
#define mem(x,y) memset(x, y, sizeof(x))
#define debug(x) cout << #x << " = " << x << '\n'
#define debug2(x,y) cout << #x << " = " << x << " " << #y << " = "<< y << '\n'
//#define int long long

using namespace std;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef pair<ull, ull> pull;
typedef pair<double, double> pdd;
/*

*/
const int maxm = 2e5 + 5, inf = 0x3f3f3f3f;

const int N = 1e6 + 10, mod = 1e9 + 7;
ll fact[N], finv[N];
ll qpow(ll a, ll x){//带模快速幂
	ll res = 1;
	while(x){
		if(x & 1) res = res * a % mod;
		x >>= 1;
		a = a * a % mod;
	}
	return res;
}

void pre(){//线性预处理
	fact[0] = 1;
	for(int i = 1; i < N; ++ i){
		fact[i] = fact[i - 1] * i % mod;
	}
	finv[0] = 1;
	finv[N - 1] = qpow(fact[N - 1], mod - 2);
	for(int i = N - 2; i > 0; -- i)
		finv[i] = finv[i + 1] * (i + 1) % mod;
	return ;
}

ll C(int a, int b){//求取组合数
	if(a < 0 || b < 0) return 1;
	return fact[a] * finv[b] % mod * finv[a - b] % mod;
}

void solve(){
	int n, m;
	cin >> n >> m;
	vector<int> d(n + 1, 0);
	for(int i = 0; i < m; ++ i){
		int u, v;
		cin >> u >> v;
		++ d[u]; ++ d[v];
	}
	ll ans = 0;
	vector<int> cnt(n + 1, 0);
	for(int i = 1; i <= n; ++ i){
		if(d[i] >= 2){
			for(int j = 2; j <= min(n - 1, d[i]); ++ j){
				cnt[j] = (cnt[j] + C(d[i], j)) % mod;
			}
		}
	}
	for(int i = 2; i <= n - 1; ++ i){
		ans ^= cnt[i];
	}
	cout << ans << '\n';
	return ;
}

signed main(){
	ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
	pre();
	int _ = 1;
	cin >> _;
	while(_ --){
		solve();
	}
	return 0;
}
posted on 2023-08-01 19:16  Qiansui  阅读(12)  评论(0编辑  收藏  举报