SDU Open 2021 Fall 题解

补体记录: B D G H

B    A+B

这道题虽然我的大致思路和题解差不多 也是利用b的长度来处理 但我处理枚举等能力太弱了 根本不知道可以直接暴力枚举来统计答案 结果就抛弃了这个想法 导致浪费了几小时吃土


#include<bits/stdc++.h>
using namespace std;
#define int long long
int ans = 0;
int n;
int pow1(int a, int b)
{
	if (b == 0)
		return 1;
	int res = 1;
	while (b)
	{
		if (b & 1)
		{
			res = res * a;
		}
		a = a * a;
		b >>= 1;
	}
	return res;
}
signed main()
{
	cin >> n;

	int len = log10(n)+1;
//	cout << len << endl;
	for (int i = 1; i <=len; i++)
	{
		for (int j = 0; j <=i; j++)
		{
			for (int k = 0; k <= i; k++)
			{
				int p = pow1(2, j)*pow1(5, k);
				int l = pow1(10, i-1), r = min(n, pow1(10, i) - 1);
				ans += (r / p - (l - 1) / p);
			}
		}
	}
	cout << ans;
}

D: 

这个构造题要是没对二进制有一定理解是写不出来的

 

#include<algorithm>
#include<set>
#include<string>
#include<cstring>
#include<iostream>
using namespace std;
#define int long long
const int maxn = 1e5 + 10;
void solve()
{
	set<int>s;
	while (s.size())
		s.erase(*s.begin());
	string now ;
	for (int i = 0; i <= 31; i++){
		cout << "+ " << i << endl;
		s.insert(i);
		cin >> now;
		if (now == "YES")
		{
			string ss;
			for (int j = 0; j < i; j++)
			{
				cout << "- " << j<<endl;
				cin >> ss;
				s.erase(j);
				if (ss == "NO")
				{
					cout << "! " << i - j << endl;
					cin >> ss;
				
					return;
				}
			}
	     }
	}
	for (int i = 1; i <= 32; i++)
	{
		int x = 32 * i + 31;
		cout << "+ " << x << endl;
		s.insert(x);
		cin >> now;
		if (now == "YES")
		{
			string ss;
			for (int j = 0; j <= 31; j++)
			{
				cout << "- " << j<<endl;
				cin >> ss;
				s.erase(j);
				if (ss == "NO")
				{
					cout << "! " << x - j << endl;
					cin >> ss;
					return;
				}
			}
		}
	}
}
signed main()
{
	int t;
	cin >> t;
	while (t--)
		solve();
}

G :

 

#include<iostream>
#include<algorithm>
using namespace std;
#define int long long
const int maxn = 1e6 + 10;
const int mod = 1e9 + 7;
int dp[maxn][8];//dp[i][j]代表数字i 最大位数为j的方案数
signed main()
{
	int n;
	cin >> n;
	for (int i = 1; i <= n; i++)
	{
		if (i >= 1)
		{

			if (i == 1)
			{
				dp[i][1] = 1;
			}
			else
			{
				dp[i][1] += dp[i - 1][1];
				dp[i][1] %= mod;
			}
		}
		 if (i >= 2)
		{
			if (i == 2)
			{
				dp[2][2] = 1;
			}
			else
			{
				dp[i][2] += dp[i - 2][1] + dp[i - 2][2];
				dp[i][2] %= mod;
			}
		}
		 if (i >= 3)
		 {
			 if (i == 3)
				 dp[3][3] = 1;
			 else
			 {
				 dp[i][3] += dp[i - 3][1] + dp[i - 3][2] + dp[i - 3][3];
				 dp[i][3] %= mod;
			 }
		 }
		 if (i >= 5)
		 {
			 if (i == 5)
				 dp[5][5] = 1;
			 else
			 {
				 dp[i][5] += dp[i - 5][1] + dp[i - 5][2] + dp[i - 5][5]+dp[i-5][3];
				 dp[i][5] %= mod;
			 }
	     }
		if (i >= 7)
		{
			if (i == 7)
				dp[7][7] = 1;
			else
			{
				dp[i][7] += dp[i - 7][7] + dp[i - 7][1] + dp[i - 7][2] + dp[i - 7][5]+dp[i-7][3];
				dp[i][7] %= mod;
			}
		}
	}
	int ans = 1;
	for (int i = 1; i <= 7; i++)
		(ans += dp[n][i]) %= mod;
	cout << ans;
}

 

H: 思路参考 :middle(洛谷)

 

#include<iostream>
#include<algorithm>
using namespace std;
#define int long long
const int maxn = 3e5 + 10;
struct node
{
	int l, r;
	int pref_max, pref_min, sum, suff_max, suff_min;
}tree[maxn<<2];
int a[maxn], cnt[maxn];
int b[maxn];
void pushup(int rt){
	tree[rt].sum = tree[rt << 1].sum + tree[rt << 1 | 1].sum;
	tree[rt].pref_max = max(tree[rt << 1].pref_max, tree[rt << 1].sum + tree[rt << 1 | 1].pref_max);
	tree[rt].suff_max = max(tree[rt << 1 | 1].suff_max, tree[rt << 1 | 1].sum + tree[rt << 1].suff_max);
	tree[rt].pref_min = min(tree[rt << 1].pref_min, tree[rt << 1].sum + tree[rt << 1 | 1].pref_min);
	tree[rt].suff_min = min(tree[rt << 1 | 1].suff_min, tree[rt << 1 | 1].sum + tree[rt << 1].suff_min);
}
void build(int rt, int l, int r)
{
	tree[rt].l = l, tree[rt].r = r;
	if (l == r)
	{
		tree[rt].pref_max = tree[rt].pref_min = tree[rt].suff_max = tree[rt].suff_min = tree[rt].sum = b[l];
		return;
	}
	int mid = l + r >> 1;
	build(rt << 1, l, mid);
	build(rt << 1 | 1, mid + 1, r);
	pushup(rt);
}
void modify(int rt, int l, int r, int q, int v)//单点
{
	if (l == q && r == q)
	{
		tree[rt].pref_max = tree[rt].pref_min = tree[rt].suff_max = tree[rt].suff_min = tree[rt].sum = v;
		return;
	}
	int mid = l + r >> 1;
	if (q <= mid)
		modify(rt << 1, l, mid, q, v);
	else
		modify(rt << 1 | 1, mid + 1, r, q, v);
	pushup(rt);
}
int querysum(int rt, int l, int r, int ql, int qr)
{
	if (l == ql && r == qr)
		return tree[rt].sum;
	int mid = l + r >> 1;
	if (qr <= mid)
		return querysum(rt << 1, l, mid, ql, qr);
	else if (ql > mid)
		return querysum(rt << 1 | 1, mid + 1, r, ql, qr);
	else
	{
		int ret = querysum(rt << 1, l, mid, ql, mid);
		ret += querysum(rt << 1|1, mid + 1, r, mid + 1, qr);
		return ret;
	}
}
int queryprefmax(int rt, int l, int r, int ql, int qr)
{
	if (l == ql && r == qr)
		return tree[rt].pref_max;
	int mid = l + r >> 1;
	if (qr <= mid)
	{
		return queryprefmax(rt << 1, l, mid, ql, qr);
	}
	else if (ql > mid)
		return queryprefmax(rt << 1 | 1, mid + 1, r, ql, qr);
	else
	{
		int ret = queryprefmax(rt << 1, l, mid, ql, mid);
		int ret2 = querysum(rt << 1, l, mid, ql, mid) + queryprefmax(rt << 1 | 1, mid + 1, r, mid + 1, qr);
		return max(ret, ret2);
	}
}
int queryprefmin(int rt, int l, int r, int ql, int qr)
{
	if (l == ql && r == qr)
		return tree[rt].pref_min;
	int mid = l + r >> 1;
	if (qr <= mid)
		return queryprefmin(rt << 1, l, mid, ql, qr);
	else if (ql > mid)
		return queryprefmin(rt << 1 | 1, mid+1, r, ql, qr);
	else
	{
		int ret = queryprefmin(rt << 1, l, mid, ql, mid);
		int ret2 = querysum(rt << 1, l, mid, ql,mid) + queryprefmin(rt << 1 | 1, mid + 1, r, mid + 1, qr);
		return min(ret, ret2);
	}
}
int querysuffmax(int rt, int l, int r, int ql, int qr)
{
	if (l == ql && r == qr)
		return tree[rt].suff_max;
	int mid = l + r >> 1;
	if (qr <= mid)
	{
		return querysuffmax(rt << 1, l, mid, ql, qr);
	}
	else if (ql > mid)
		return querysuffmax(rt << 1 | 1, mid + 1, r, ql, qr);
	else
	{
		int ret = querysuffmax(rt << 1|1, mid+1,r, mid+1,qr);
		int ret2 = querysum(rt << 1|1, mid+1, r, mid+1, qr) + querysuffmax(rt << 1, l, mid,ql,mid);
		return max(ret, ret2);
	}
}
int querysuffmin(int rt, int l, int r, int ql, int qr)
{
	if (l == ql && r == qr)
		return tree[rt].suff_min;
	int mid = l + r >> 1;
	if (qr <= mid)
		return querysuffmin(rt << 1, l, mid, ql, qr);
	else if (ql > mid)
		return querysuffmin(rt << 1 | 1, mid + 1, r, ql, qr);
	else
	{
		int ret = querysuffmin(rt << 1|1, mid+1, r, mid+1, qr);
		int ret2 = querysum(rt << 1|1, mid+1, r, mid+1, qr) + querysuffmin(rt << 1 , l, mid,ql,mid);
		return min(ret, ret2);
	}
}
void solve(){
	int n;
	cin >> n;
	for (int i = 1; i <= n; i++)
	{
		cin >> a[i];
		if (a[i] < 1)
			b[i] = -1;
		else if (a[i] == 1)
			b[i] == 0;
		else
			b[i] = 1;
		cnt[a[i]] = i;
	}
	build(1, 1, n);
	for (int i = 1; i <= n; i++)
	{
		//cout << i << endl;
			int preemax = 0, preemin = 0;
			int suffmax = 0, suffmin = 0;
			if (cnt[i] != 1)//代表前面有数
			{
				preemax = querysuffmax(1, 1, n, 1, cnt[i]-1);
				preemin =querysuffmin(1, 1, n, 1, cnt[i]-1);
			//1 左边是0
				if (preemin <= 0 && preemax >= 0)
				{
					cout << "y";
					modify(1, 1, n, cnt[i], -1);
					if(i!=n)
					modify(1, 1, n, cnt[i + 1], 0);
					continue;
				}
			}
			if (cnt[i] != n)//代表后面有数
			{
				suffmax =queryprefmax(1, 1, n, cnt[i]+1, n);
				suffmin =queryprefmin(1, 1, n, cnt[i]+1, n);
				if (suffmax >= 0 && suffmin <= 0)
				{
					cout << 'y';
					modify(1, 1, n, cnt[i], -1);
					if(i!=n)
					modify(1, 1, n, cnt[i + 1], 0);
					continue;
			  }
			}
			if (cnt[i] == n)//代表后米面没有数
			{
				if (preemax >= 0 && preemin <= 0)//代表前面有数
				{
					cout << 'y';
				}
				else
					cout << 'n';
			}
			else if (cnt[i] == 1)
			{
				if (suffmin <= 0 && suffmax >= 0)
				{
					cout << 'y';
				}
				else
					cout << 'n';
			}
			else
			{
				if (preemin <= -suffmin && preemax >= -suffmax)
				{
					cout << 'y';
				}
				else
					cout << "n";
			}
			modify(1, 1, n, cnt[i], -1);
			if(i!=n)
			modify(1, 1, n, cnt[i + 1], 0);
			//cout << endl;
	}
	cout <<'\n';
}
signed main()
{
	ios::sync_with_stdio(false);
	cin.tie(0), cout.tie(0);
	int t;
	cin >> t;
	while (t--)
		solve();
}

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值