2016 icpc沈阳部分题解

hdu5948 hdu5949 hdu5950 hdu5952 hdu5954

A Thickest Burger

​ 对于每对 A B, 输出 m a x ( 2 A + B , 2 B + A ) max(2A + B, 2B + A) max(2A+B,2B+A)

B Relative atomic mass

​ 给出一个字符串,只包含CHO,原子质量分别是12,1,16,求出这个字符串总的质量即可

C Recursive sequence

​ 矩阵快速幂,式子是 a [ i ] = 2 a [ i − 2 ] + a [ i − 1 ] + i 4 a[i] = 2a[i - 2] + a[i - 1] + i^4 a[i]=2a[i2]+a[i1]+i4,关键在于根据这个式子推导出转移矩阵,然后直接 l o g n logn logn 实现即可

#include<bits/stdc++.h>
using namespace std;

#define int long long
const int mod =  2147493647;

struct matrix{
	int a[8][8];

	matrix(){
		memset(a, 0, sizeof a);
	}
};

matrix mul(const matrix& x, const matrix& y){
	matrix ans;
	for(int i = 0; i < 7; ++i){
		for(int j = 0; j < 7; ++j){
			for(int k = 0; k < 7; ++k){
				ans.a[i][j] += x.a[i][k] * y.a[k][j];
				ans.a[i][j] %= mod;
			}
		}
	}
	return ans;
}

matrix qpow(matrix a, int b){
	matrix ans;
	memcpy(ans.a, a.a, sizeof a.a);
	if(b == 0) return ans;
	b--;
	while(b){
		if(b & 1LL) ans = mul(ans, a);
		a = mul(a, a);
		b >>= 1LL;
	}	
	return ans;
}

signed main(){
	matrix A, B;
	A.a[0][2] = 16;
	A.a[0][3] = 8;
	A.a[0][4] = 4;
	A.a[0][5] = 2; 
	A.a[0][6] = 1;

	B.a[0][0] = B.a[0][1] = 1;
	B.a[1][0] = 2;
	B.a[2][0] = B.a[2][2] = 1;
	B.a[3][0] = B.a[3][2] = 4;
	B.a[3][3] = 1;
	B.a[4][0] = B.a[4][2] = 6;
	B.a[4][3] = 3;
	B.a[4][4] = 1;
	B.a[5][0] = B.a[5][2] = 4;
	B.a[5][3] = 3;
	B.a[5][4] = 2;
	B.a[5][5] = 1;
	for(int i = 0; i < 7; ++i)
		B.a[6][i] = 1;
	B.a[6][1] = 0;

	int t;
	cin >> t;
	while(t--){
		int n, a, b;
		cin >> n >> a >> b;
		matrix C = A, D = B;
		C.a[0][1] = a;
		C.a[0][0] = b;
		if(n == 1){
			cout << a << endl;
			continue;
		}
		else if(n == 2){
			cout << b << endl;
			continue;
		}
		n -= 2;
		D = qpow(D, n);
		C = mul(C, D);
		cout << C.a[0][0] << endl;
	}
	return 0;
}

D Couting Cliques

​ 给出一个无向图,有n个顶点和m条边,求顶点刚好为S的完全子图。
​ 这里因为n只有100,m只有1000,S不超过10,所以直接爆搜,然后剪枝即可(一开始的时候还在苦苦想着有没有更好的想法,大意了)

#include<bits/stdc++.h>
using namespace std;

const int N = 111;

const int M = 1111;
int e[M], ne[M], h[N], idx;

void add(int a, int b){
	e[idx] = b;
	ne[idx] = h[a];
	h[a] = idx++;
}

int vis[N];
int mp[N][N];
int n, m, s;
int ans;
int a[11];
int at;


inline int read() {
    int X = 0; bool flag = 1; char ch = getchar();
    while (ch < '0' || ch>'9') { if (ch == '-') flag = 0; ch = getchar(); }
    while (ch >= '0' && ch <= '9') { X = (X << 1) + (X << 3) + ch - '0'; ch = getchar(); }
    if (flag) return X;
    return ~(X - 1);
}


void dfs(int now){
	if(at == s){
		ans++;
		return;
	}
	for(int i = h[now]; i != -1; i = ne[i]){
		int y = e[i];
		int flag = 1;
		if(y < now) continue;
		for(int j = 0; j < at; ++j){
			int z = a[j];
			if(mp[y][z] == 0){
				flag = 0;
				break;
			}
		}
		if(flag){
			a[at++] = y;
			dfs(y);
			at--;
		}
	}
}

signed main(){
	int t;
	t = read();
	while(t--){
		memset(mp, 0, sizeof mp);
		memset(h, -1, sizeof h);
		idx = 0;
		ans = 0;
		at = 0;
		n = read(), m = read(), s = read();
		for(int i = 0; i < m; ++i){
			int u, v;
			u = read(), v = read();
			add(u, v);
			mp[u][v] = mp[v][u] = 1;
		}
		for(int i = 1; i <= n - s + 1; ++i){
			a[at++] = i;
			dfs(i);
			at--;
		}
		printf("%d\n", ans);
	}
	return 0;
}

E Do not pour out

​ 当d >= 1 时,上面是一个完整的椭圆,用简单的推算直接求出椭圆的 a a a b b b,椭圆面积公式 π a b \pi ab πab 即可。

​ 关键是当 d < 1时,椭圆面是会被截去一部分的,如图
在这里插入图片描述

​ 设 m i d , t , y mid, t, y mid,t,y,根据相似三角形得到 t m i d = 2 − y 2 \frac{t}{mid} = \frac{2 - y}{2} midt=22y,所以有 t = ( 2 − y ) m i d 2 t = \frac{(2 - y)mid}{2} t=2(2y)mid
​ 有效底面积是 θ + ( t − 1 ) s i n ( θ ) \theta + (t - 1)sin(\theta) θ+(t1)sin(θ),其中 θ = a r c c o s ( 1 − t ) \theta = arccos(1 - t) θ=arccos(1t),这里不需要特判 t t t 和 1 的大小关系,神奇的三角函数已经帮我们考虑这种关系了。

​ 所以总结一下公式
①                     t = ( 2 − y ) m i d 2 ②                  θ = a r c c o s ( 1 − t ) ③      S ( t ) = θ + ( t − 1 ) s i n ( θ ) ④                V = ∫ 0 2 S ( t ( y ) ) d y ① \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ t = \frac{(2 - y)mid}{2}\\② \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \theta = arccos(1 - t)\\③ \ \ \ \ S(t) = \theta + (t - 1)sin(\theta)\\④ \ \ \ \ \ \ \ \ \ \ \ \ \ \ V = \int_{0}^{2}S(t(y))dy                    t=2(2y)mid                θ=arccos(1t)    S(t)=θ+(t1)sin(θ)              V=02S(t(y))dy
​ 然后就是代换,③代入④得到
⑤         V = ∫ 0 2 ( θ + ( t − 1 ) s i n θ ) d y ⑤\ \ \ \ \ \ \ V = \int_{0}^{2}(\theta + (t - 1)sin\theta)dy        V=02(θ+(t1)sinθ)dy
​ 由①得 y = 2 − 2 t m i d y = 2 - \frac{2t}{mid} y=2mid2t,所以得到
⑥        d y = − 2 m i d s i n θ   d θ ⑥\ \ \ \ \ \ dy = -\frac{2}{mid}sin\theta \ d\theta       dy=mid2sinθ dθ
​ 由②
⑦       t = 1 − c o s θ ⑦\ \ \ \ \ t = 1 - cos\theta      t=1cosθ
​ ⑦代入⑤得到
⑧          V = ∫ 0 2 ( θ − s i n θ c o n θ ) d y ⑧\ \ \ \ \ \ \ \ V =\int_{0}^{2}(\theta - sin\theta con\theta)dy         V=02(θsinθconθ)dy
​ ⑥代入⑧ 得到
⑨           V = − 2 m i d ∫ a b ( ( θ − s i n θ c o s θ ) s i n θ ) d θ ⑨\ \ \ \ \ \ \ \ \ V = -\frac{2}{mid}\int_{a}^{b}((\theta - sin\theta cos\theta)sin\theta)d\theta          V=mid2ab((θsinθcosθ)sinθ)dθ
​ 得到的⑨式中的积分区间是发生了变化的,从原来的对 y y y 积分变成了对 θ \theta θ 积分,这里根据 公式⑥进行新区间范围计算 [ a r c c o s ( 1 − m i d ) , a r c c o s ( 1 ) ] [arccos(1 - mid), arccos(1)] [arccos(1mid),arccos(1)],所以最后的积分公式为
⑩           V = − 2 m i d ∫ a r c c o s ( 1 − m i d ) a r c c o s ( 1 ) ( θ s i n θ − s i n 2 θ c o s θ ) d θ ⑩\ \ \ \ \ \ \ \ \ V = -\frac{2}{mid}\int_{arccos(1 - mid)}^{arccos(1)}(\theta sin\theta - sin^2\theta cos\theta)d\theta          V=mid2arccos(1mid)arccos(1)(θsinθsin2θcosθ)dθ

​ 然后就是求积分了,的到最后需要实现的计算公式
V = − 2 m i d [ s i n ( x ) − x c o s ( x ) − 1 3 s i n 3 ( x ) ] a c o s ( a − m i d ) a c o s ( 1 ) V = -\frac{2}{mid}[sin(x) - x cos(x) - \frac{1}{3}sin^3(x)]_{acos(a - mid)}^{acos(1)} V=mid2[sin(x)xcos(x)31sin3(x)]acos(amid)acos(1)
​ 这样就可以通过二分求 m i d mid mid,得到 m i d mid mid 之后,可以求出斜面和底面的夹角 α \alpha α,根据图形得到以下关系
c o s α = m i d 2 2 + m i d 2 = S 底 S 0 cos \alpha = \frac{mid}{\sqrt{2^2 + mid^2}} = \frac{S_底}{S_0} cosα=22+mid2 mid=S0S
​ 这里 S 0 S_0 S0 表示斜面面积, S 底 S_底 S 表示 S 0 S_0 S0 在底面的投影, S 底 S_底 S 可以用②③公式求出来,所以答案就是
S 0 = S 底 2 2 + m i d 2 m i d S_0 = \frac{S_底 \sqrt{2^2 + mid^2}}{mid} S0=midS22+mid2

#include<bits/stdc++.h>
using namespace std;
const double PI = acos(-1.0);
const double eps = 1e-10;

double f(double x){
	return sin(x) - x * cos(x) - pow(sin(x), 3) / 3;
}

double getV(double mid){
	double a = acos(1 - mid);
	double b = acos(1);
	return -2.0 / mid * (f(b) - f(a));
}

double getS(double t){
	double theta =  acos(1 - t);
	return theta + (t - 1) * sin(theta);
}

int main(){
	int t;
	cin >> t;
	while(t--){
		double d;
		cin >> d;
		if(fabs(d) < eps){
			printf("%.5f\n", 0);
			continue;
		}
		if(d < 1){
			double l = 0, r = 2;
			while(fabs(r - l) > eps){
				double mid = (l + r) / 2;
				if(getV(mid) < PI * d)
					l = mid;
				else r = mid;
			}
			double mid = (l + r) / 2;
			double S = getS(mid);
			double S1 = S * sqrt(4 + mid * mid) / mid;
			printf("%.5f\n", S1);
		}
		else{
			double a = sqrt(1 + (2 - d) * (2 - d));
			double b = 1;
			double S = PI * a * b;
			printf("%.5f\n", S);
		}
	}
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值