zoukankan      html  css  js  c++  java
  • 20191011模拟赛

    T1

    题目大意

    给定一个长方体的体积(v),确定其长宽高(a,b,c)使得其长方体的表面积最小。

    思路

    根据均值不等式:

    (a+b+c geq 3 imes^3 sqrt{abc})

    代入(2ab, 2bc, 2ac),即可得到(ab+bc+ac geq 6 imes^3 sqrt{v^2}),当且仅当(a=b=c)时成立。

    我们发现这个右边的式子不能直接进行计算,考虑牛顿迭代或暴力枚举。

    但是(a=b=c)这个条件不一定能满足,因为题目限制(a,b,c in mathbb{Z})。所以我们应该使(a,b,c)三者尽量靠近。

    故可以通过枚举(a,b),表达出(c),统计即可。

    复杂度为(O(V^{frac{2}{3}}))

    代码

    #include <bits/stdc++.h>
    const int INF = 2147483646;
    typedef int intt;
    #define int long long
    using namespace std;
    int v, res, ans = INF;
    int calc(int a, int b, int c) { return ((a * b) << 1) + ((b * c) << 1) + ((a * c) << 1); }
    intt main() {
    	cin >> v;
    	for(int i = 1; i * i * i <= v; i++) {
    		if(v % i != 0)
    			continue;
    		res = calc(i, sqrt(v / i), sqrt(v / i));
    		if(res > ans)
    			continue;
    		for(int j = 1; j * j <= (v / i); j++) {
    			if((v / i) % j != 0)
    				continue;
    			ans = min(ans, calc(i, j, (v / i) / j));
    		}
    	}
    	cout << ans << endl;
    	return 0;
    }
    

    牛顿迭代版:

    #include <bits/stdc++.h>
    const int lim = 100;
    typedef long long ll;
    using namespace std;
    long double x, v;
    int main() {
    	cin >> v;
    	v *= v;
    	x = 10;
    	for(int i = 1; i <= lim; i++)
    		x = x - (x * x * x - v) / (3 * x * x);
    	cout << 6 * x << endl;
    	return 0;
    }
    

    T2

    题目大意

    给定一个字符串,计算出所有互不相交的回文子串对的个数。

    思路

    (90pts:)处理出所有的回文子串的(l,r),然后按左端点,右端点排序,枚举每个区间,二分出第一个互不相交的区间,累加其及其之后的答案即可。复杂度为(O(n^3 + p imes logn)),其中(p)为回文区间总数。(ps:(n^3)是指我之前的回文序列的判断与统计,十分暴力...)

    (100pts:)首先优化回文序列的寻找过程。枚举每一个点,然后递归扩展左右,然后使用树状数组维护前缀和,最后枚举查询,查询到是区间右端点比当前区间左端点小的个数,累加即可。

    代码

    (90pts:)

    #include <bits/stdc++.h>
    const int MAXN = 2050;
    using namespace std;
    char s[MAXN];
    int len, num, ans;
    struct node {
    	int l, r;
    	bool operator < (const node &a) const {
    		return a.l == l ? a.r > r : a.l > l;
    	}
    }a[200000000];
    bool check(int x, int y) {
    	for(int i = x, j = y; i <= j; i++, j--) {
    		if(s[i] != s[j])
    			return false;
    	}
    	return true;
    }
    bool check1(int x, int y) { return a[x].l > a[y].r; }
    int main() {
    	cin >> s + 1;
    	len = strlen(s + 1);
    	for(int i = 1; i <= len; i++) {
    		for(int j = i; j <= len; j++) {
    			if(check(i, j))
    				a[++num] = (node){i, j};
    		}
    	}
    	sort(a + 1, a + num + 1);
    	for(int i = 1; i <= num; i++) {
    		int l = i + 1, r = num, res = 0;
    		while(l <= r) {
    			int mid = (l + r) >> 1;
    			if(check1(mid, i)) {
    				res = mid;
    				r = mid - 1;
    			}
    			else
    				l = mid + 1;
    		}
    		if(res != 0)
    			ans += (num - res + 1);
    	}
    	cout << ans << endl;
    	return 0;
    }
    

    (100pts:)

    #include <bits/stdc++.h>
    const int MAXN = 2050;
    typedef int intt;
    #define int long long
    using namespace std;
    char s[MAXN];
    int len, num, ans, c[MAXN];
    struct node {
    	int l, r;
    }a[20000000];
    int lowbit(int x) { return x & (-x); }
    void add(int x) {
    	while(x <= len) {
    		c[x]++;
    		x += lowbit(x);
    	}
    }
    int query(int x) {
    	int res = 0;
    	while(x > 0) {
    		res += c[x];
    		x -= lowbit(x);
    	}
    	return res;
    }
    void solve(int l, int r) {
    	if(l == 0 || r == len + 1)
    		return ;
    	a[++num] = (node){l, r};
    	add(r);
    	if(s[l - 1] == s[r + 1])
    		solve(l - 1, r + 1);
    }
    intt main() {
    	cin >> s + 1;
    	len = strlen(s + 1);
    	for(int i = 1; i <= len; i++) {
    		solve(i, i);
    		if(s[i] == s[i + 1])
    			solve(i, i + 1);
    	}
    	for(int i = 1; i <= num; i++)
    		ans += query(a[i].l - 1);
    	cout << ans << endl;
    	return 0;
    }
    

    T3

    题目大意

    给定两个升序序列(A,B),当(A[i]-x leq B[j] leq A[i]+y)时则可以将(A[i])(B[j])匹配。求最大匹配数。

    思路

    (50pts:)(dp),设(f[i][j])表示(A)中前(i)个数和(B)中前(j)个数的最大匹配数。直接简单的转移即可,复杂度为(O(n^2))

    (100pts:)由于升序,且区间长度一定,则可以进行贪心的选取,即尽可能让每一个点和一个右端点尽量靠左的区间进行匹配,尽可能最大的利用区间,让剩下的点有更多的机会去匹配。实现只需要用两个指针即可。复杂度为(O(n))

    代码

    (50pts:)

    #include <cstdio>
    #include <cctype>
    #include <cstring>
    #include <iostream>
    const int MAXN = 1050;
    using namespace std;
    int n, m, x, y, a[MAXN], b[MAXN], f[MAXN][MAXN];
    int main() {
    	cin >> n >> m >> x >> y;
    	for(int i = 1; i <= n; i++)
    		cin >> a[i];
    	for(int i = 1; i <= m; i++)
    		cin >> b[i];
    	for(int i = 1; i <= n; i++) {
    		for(int j = 1; j <= m; j++) {
    			if(a[i] - x <= b[j] && a[i] + y >= b[j])
    				f[i][j] = max(f[i][j], f[i - 1][j - 1] + 1);
    			else
    				f[i][j] = max(f[i - 1][j - 1], max(f[i - 1][j], f[i][j - 1]));
    		}
    	}
    	cout << f[n][m] << endl;
    	return 0;
    }
    

    (100pts:)

    #include <bits/stdc++.h>
    const int MAXN = 100050;
    using namespace std;
    struct node {
    	int x, y;
    }g[MAXN];
    int n, m, x, y, c, p1 = 1, p2 = 1, ans, f[MAXN];
    bool flag;
    int main() {
    	cin >> n >> m >> x >> y;
    	for(int i = 1; i <= n; i++) {
    		cin >> c;
    		g[i].x = c - x;
    		g[i].y = c + y;
    	}
    	for(int i = 1; i <= m; i++)
    		cin >> f[i];
    	while(p1 <= n && p2 <= m) {
    		if(f[p2] >= g[p1].x && f[p2] <= g[p1].y) {
    			ans++;
    			p1++;
    			p2++;
    		}
    		else if(f[p2] > g[p1].y)
    			p1++;
    		else if(f[p2] < g[p1].x)
    			p2++; 
    	}
    	cout << ans << endl;
    	return 0;
    }
    
  • 相关阅读:
    Collection和Collections的区别
    Demo小细节-1
    一道关于String的面试题,新鲜出炉,刚被坑过,趁热!!
    System.gc()与Object.finalize()的区别
    释放对象所占用的内存
    Java接口中的成员变量默认为(public、static、final)、方法为(public、abstract)
    纸牌游戏——队列和栈的应用
    Vue过渡动画运用transition
    SpringBoot整合Redis注意的一些问题
    Spring的Bean的生命周期
  • 原文地址:https://www.cnblogs.com/BeyondLimits/p/11663663.html
Copyright © 2011-2022 走看看