2019牛客寒假算法基础集训1

题解

A-小a的计算器

根据题意反向模拟即可

#include <cstdio>
#define ll long long
int n;
ll ans, a[105], b[105];

int main()
{
	scanf("%d%lld", &n, &ans);
	for (int i = 0; i < n; ++i)
		scanf("%lld%lld", &a[i], &b[i]);
	while (n--){
		switch(a[n]) {
			case 1: ans -= b[n]; break;
			case 2: ans += b[n]; break;
			case 3: ans /= b[n]; break;
			case 4: ans *= b[n]; break;
		}
	}
	printf("%lld\n", ans);
	return 0;
}

B-小a与"204"

广 推广到一般情况,第一个位置放最大,第二个位置放最小,第三个位置放第二大,以此类推

#include <cstdio>
#include <algorithm>
using namespace std;
const int MAX_N = 1e5 + 5;
int n, a[MAX_N], b[MAX_N], ans, x, y;

int main()
{
	scanf("%d", &n);
	for (int i = 1; i <= n; ++i)
		scanf("%d", &a[i]);
	sort(a, a + n + 1);
	while (y != n / 2){
		b[x++] = a[y];
		b[x++] = a[n - y];
		y++;
	}
	if (n & 1) {
		b[x++] = a[y];
		b[x] = a[n - y];
	}
	else b[x] = a[y];
	//for(int i = 0; i <= x; ++i) printf("%d ", b[i]); printf("\n");
	for (int i = 1; i <= x; ++i)
		ans += (b[i] - b[i - 1]) * (b[i] - b[i - 1]);
	printf("%d\n", ans);
	return 0;
}

C-小a与星际探险

d p 背包dp问题
: ( 牵涉到位运算符:与( & ) , ( ),非( ~ ) , ( ),或( | ) , ( ),异或( ^ ) )

#include <cstdio>
const int N = 3010, M = 1 << 12;
int n, ans, dp[M], p[N], a[N];

int max(int a, int b)
{
	return a > b ? a : b;
}

inline int Read(){
    int x = 0, f = 1; char c = getchar();
    while (c < '0' || c > '9') {if(c == '-') f = -1; c = getchar();}
    while (c >= '0' && c <= '9') x = (x << 3) + (x << 1) + c - '0', c = getchar();
    return x * f;
}

int main()
{
	n = Read();
	for (int i = 1; i <= n; ++i){
		p[i] = Read();
	}
	if (p[1] <= p[n]){
		printf("-1\n");
		return 0;
	}
	ans = p[1] ^ p[n];
	dp[ans] = 1;
	for (int i = 2; i <= n; ++i){
		if (p[i] < p[1] && p[i] > p[n])
		for (int j = 0; j < M; ++j){
			dp[j] |= dp[j ^ p[i]];
			ans = max(ans, dp[j] * j);
		}
	}
	if(!ans) printf("-1\n");
	else printf("%d\n", ans);
	return 0;
}

D-小a与黄金街道

g c d ( n , x ) = g c d ( n , n x ) n n ( A + B ) k φ ( n ) 2 n 由于gcd(n,x)=gcd(n,n-x),小于n的正整数中与n互质的数的数目即欧拉函数,\\由对称性易得答案(A+B)*k^{\frac{\varphi(n)}{2}n}

#include <cstdio>
#define ll long long
const int mod = 1e9 + 7;
ll n, A, B, k, tmp;

ll phi(ll x)
{
	ll ans = x;
	for (int i = 2; i * i <= x; ++i) {
		if(x % i == 0) {
			ans -= ans / i;
			while (x % i == 0) x /= i;
		}
	}
	if (x > 1) ans -= ans/x;
	return ans;
}

ll qpow(ll a, ll b)
{
	ll ans = 1;
	for(; b; b >>= 1){
		if(b & 1) ans = (ans % mod) * (a % mod) % mod;
		a = (a % mod) * (a % mod);
	}
	return ans;
}

int main()
{
	scanf("%lld%lld%lld%lld", &n, &k, &A, &B);
	tmp = n * phi(n) / 2;
	printf("%lld\n", (A + B) * qpow(k, tmp) % mod);
	return 0;
}

E-小a的轰炸游戏



F-小a的子序列

d p [ i ] [ j ] i , j , 1. j i 1 j 1 j ( d p [ i 1 ] [ j 1 ] ( j 1 ) ) i 1 j ( d p [ i 1 ] [ j ] d p [ i 1 ] [ j 1 ] ) 2. j d p [ i ] [ j 1 ] d p [ i ] [ j ] = d p [ i 1 ] [ j 1 ] ( j 1 ) + d p [ i 1 ] [ j ] d p [ i 1 ] [ j 1 ] + d p [ i ] [ j 1 ] d p [ i ] [ j ] = k = 1 j 1 d p [ i 1 ] [ k ] k + d p [ i 1 ] [ j ] + 1 考虑dp[i][j]表示长度为i,最大值为j的全部答案,\\ {\bf1}.序列包含j的由长度为i-1最大值为j-1的插入一个j(dp[i-1][j-1]*(j-1))\\ 及长度为i-1且包含j的序列加一个不选的位置(dp[i-1][j]-dp[i-1][j-1])\\贡献\\ {\bf2}.序列不包含j的由dp[i][j-1]贡献\\得递推式:\\ dp[i][j]=dp[i-1][j-1]*(j-1)+dp[i-1][j]-dp[i-1][j-1]+dp[i][j-1]\\ 化为dp[i][j]=\displaystyle\sum_{k=1}^{j-1}dp[i-1][k]*k+dp[i-1][j]+1

#include <cstdio>
#define ll long long
const int mod = 1e9 + 7;
const int MAX_N = 5005;
int n, v;
ll ans, s, dp[MAX_N][MAX_N];

int main()
{
	scanf("%d%d", &n, &v);
	for (int i = 1; i <= v; ++i)
		dp[1][i] = 1;
	for (int i = 2; i <= n; ++i) {
		s = 1;
		for (int j = 1; j <= v; ++j) {
			dp[i][j] = (dp[i - 1][j] + s) % mod;
			s = (s + dp[i - 1][j] * j) % mod;
		}
	}
	for(int i = 1; i <= v; ++i)
		ans = (ans + dp[n][i]) % mod;
	printf("%lld\n", ans);
	return 0;
}

G-小a的排列

不断更新范围以得到答案

#include <cstdio>
#define INF 0x3f3f3f
const int MAX_N = 1e5 + 5;
int N, x, y, l, r, L, R, m, n = INF;
int a[MAX_N], p[MAX_N];

void swap(int &a, int &b)
{
	a ^= b;
	b ^= a;
	a ^= b;
}

int max(int a, int b)
{
	return a > b ? a : b;
}

int min(int a, int b)
{
	return a < b ? a : b;
}

int main()
{
	scanf("%d %d %d", &N, &x, &y);
	for (int i = 1; i <= N; ++i){
		scanf("%d", &a[i]);
		p[a[i]] = i;
	}
	L = p[x], R = p[y];
	if (L > R) swap(L, R);
	for (int i = L; i <= R; ++i) {
		m = max(m, a[i]);
		n = min(n, a[i]);
	}
	l = L, r = R;
	for (int i = n; i <= m; ++i) {
		l = min(l, p[i]);
		r = max(r, p[i]);
	}
	while(l < L || r > R) {
		if (l < L) L = l;
		if (r > R) R = r;
		for (int i = L; i <= R; ++i) { 
			m = max(m, a[i]);
			n = min(n, a[i]);
		}
		for (int i = n; i <= m; ++i) {
			l = min(l, p[i]);
			r = max(r, p[i]);
		}
	}
	printf("%d %d\n", L, R);
	return 0;
}

H-小a的学期

典型的卡特兰数


猜你喜欢

转载自blog.csdn.net/AbelYang1/article/details/86601395