2023 - 8- 28练习题

A - WOW Factor

 

ans += 出现o的位置前的w数量 * o后面的w数量 

// Problem: A - WOW Factor
// Contest: Virtual Judge - 22练习赛
// URL: https://vjudge.net/contest/578163#problem/A
// Memory Limit: 256 MB
// Time Limit: 1000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#include<iostream>
#include<algorithm>
#include<vector>
#include<set>
#include<queue>
#include<map>
#include<string>
#include<cstring>
#include<cmath>
#include<bitset>
#include<sstream>//切割strtream头文件
#include<climits>//INT_MAX文件
#include <utility>
#include<memory>//for unique_ptr shared_ptr
using i64 = int64_t;
using namespace std;
#define int i64
#define endl '\n'
#define AC return 0;
#define WA(x) cout << x << endl;
#define lowbit(x) x & -x
const int maxn = 1e6 + 10;
const int mod = 1e9 + 7;
int n, m, k, d, T = 1, A, B;

template<typename T>void read(T &x) {
    T f = 1;x = 0;char s = getchar();
    while(s < '0' || s > '9') {if(s == '-')f = -1;s = getchar();}
    while(s >= '0' && s <= '9') {x = x * 10 + s - '0';s = getchar();}
    x *= f;
}

template<typename T>void print(T x) {
    if(x < 0) putchar('-'),x = -x;
    if(x > 9) print(x / 10);
    putchar(x % 10 + '0');
    putchar('\n');
}
constexpr int Init(int x)
{
	return x * 2;
}

int pre[maxn];//前i个位置有多少个vv
void solve()
{
	auto x = make_unique<int>();
	string s;
	cin >> s;
	int n = s.size();
	s = "*" + s;
	for(int i = 1;i <= n;i++)
	{
		pre[i] = pre[i - 1] + (s[i] == 'v' && s[i - 1] == 'v');
	}
	int ans = 0;
	for(int i = 1;i <= n;i++)
	{
		if(s[i] == 'o')
		ans += (pre[i - 1] * (pre[n] - pre[i]));
	}
	cout << ans << endl;
}
 
signed main() {
    cin.tie(0) -> sync_with_stdio(false);
    int T = 1;
   	//read(T);
    while (T--) solve();
    return 0;
}

B - Mishka and the Last Exam

 

 贪心的想a[i] + a[n - i + 1] == b[i]

通过b数组构造a(非降序)则希望前者尽量小,后者尽量大

对于b[1]可以确定头and尾

则令a[n] = b[1] a[1] = 0

后面的构造也是将b[i]拆分赋值给a[i] and a[n - i + 1]

∵非降序则a[i]至少为a[i - 1]而a[n - i + 1]至少小于等于a[n - i + 2]

可得

又∵ 

很愉快的TIL

先前考虑优先满足前者

∵题目保证至少可以构造一组a,即一定有解

那么我们索性再贪一点让a[n - i  + 1] 赋值为a[n - i + 2]

那么  a[i] = b[i] - a[n - i + 1];

如果此时破坏了a的规则,则我们希望a[i]尽可能小,a[n - i + 1]尽可能大

// Problem: B - Mishka and the Last Exam
// Contest: Virtual Judge - 22练习赛
// URL: https://vjudge.net/contest/578163#problem/B
// Memory Limit: 256 MB
// Time Limit: 2000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#include<iostream>
#include<algorithm>
#include<vector>
#include<set>
#include<queue>
#include<map>
#include<string>
#include<cstring>
#include<cmath>
#include<bitset>
#include<sstream>//切割strtream头文件
#include<climits>//INT_MAX文件
#include <utility>
#include<memory>//for unique_ptr shared_ptr
using i64 = int64_t;
using namespace std;
#define int i64
#define endl '\n'
#define AC return 0;
#define WA(x) cout << x << endl;
#define lowbit(x) x & -x
const int maxn = 1e6 + 10;
const int mod = 1e9 + 7;
int n, m, k, d, T = 1, A, B;

template<typename T>void read(T &x) {
    T f = 1;x = 0;char s = getchar();
    while(s < '0' || s > '9') {if(s == '-')f = -1;s = getchar();}
    while(s >= '0' && s <= '9') {x = x * 10 + s - '0';s = getchar();}
    x *= f;
}

template<typename T>void print(T x) {
    if(x < 0) putchar('-'),x = -x;
    if(x > 9) print(x / 10);
    putchar(x % 10 + '0');
    putchar('\n');
}
constexpr int Init(int x)
{
	return x * 2;
}
int a[maxn];
int b[maxn];
void solve()
{
	auto x = make_unique<int>();
	cin >> n;
	for(int i = 1;i <= n / 2;i++)cin >> b[i];
	//b[i] = a[i] + a[n - i + 1];
	//b[1] = a[1] + a[n]
	//b[2] = a[2] + a[n - 1]
	//b[3] = a[3] + a[n - 2]
	a[1] = 0;
	a[n] = b[1];
	for(int i = 2;i <= n / 2;i++)
	{
		a[n - i + 1] = min(a[n - i + 2], b[i]);
		a[i] = b[i] - a[n - i + 1];
		if(a[i] < a[i - 1])
		{
			a[i] = a[i - 1];
			a[n - i + 1] = b[i] - a[i];
		}
	}
	for(int i = 1;i <= n;i++)
	cout << a[i] << " ";
}
 
signed main() {
    cin.tie(0) -> sync_with_stdio(false);
    int T = 1;
   	//read(T);
    while (T--) solve();
    return 0;
}

C - Queen

 

 ∵叶子节点没有儿子节点,那么就不存在儿子节点尊重它(???题目的真理)

∴我们初始化默认每一个节点都不被子节点尊重

每轮输入其子节点编号p及c(1不尊重父节点,0反之) 

其中每一个节点只存在一个父节点则显然 fa[i] = c即可

而p相对i为父节点 == > i是p的子节点

若c == 0 则p被子尊重son[p] = 0;

∵p可以有多个子节点 == >> 一次为0永久为0 && son[p]默认初始化1

则通过son[p] &= c即可

// Problem: C - Queen
// Contest: Virtual Judge - 22练习赛
// URL: https://vjudge.net/contest/578163#problem/C
// Memory Limit: 256 MB
// Time Limit: 1000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#include<iostream>
#include<algorithm>
#include<vector>
#include<set>
#include<queue>
#include<map>
#include<string>
#include<cstring>
#include<cmath>
#include<bitset>
#include<sstream>//切割strtream头文件
#include<climits>//INT_MAX文件
#include <utility>
#include<memory>//for unique_ptr shared_ptr
using i64 = int64_t;
using namespace std;
#define int i64
#define endl '\n'
#define AC return 0;
#define WA(x) cout << x << endl;
#define lowbit(x) x & -x
const int maxn = 1e5 + 10;
const int mod = 1e9 + 7;
int n, m, k, d, T = 1, A, B;

template<typename T>void read(T &x) {
    T f = 1;x = 0;char s = getchar();
    while(s < '0' || s > '9') {if(s == '-')f = -1;s = getchar();}
    while(s >= '0' && s <= '9') {x = x * 10 + s - '0';s = getchar();}
    x *= f;
}

template<typename T>void print(T x) {
    if(x < 0) putchar('-'),x = -x;
    if(x > 9) print(x / 10);
    putchar(x % 10 + '0');
    putchar('\n');
}
constexpr int Init(int x)
{
	return x * 2;
}

int fa[maxn];//i 是否尊重父亲
int son[maxn];// 是否被儿子尊重

void solve()
{
	auto x = make_unique<int>();
	cin >> n;
	memset(son, 1, sizeof son);
	for(int i = 1;i <= n;i++)
	{
		int p, c;
		cin >> p >> c;
		if(-1 == p)continue;	
		fa[i] = c;
		son[p] &= c;
		
	}
	
	bool is = false;
	for(int i = 1;i <= n;i++)
	{
		if(fa[i] && son[i])
		{
			is = true;
			cout << i << " ";
		}
	}
	if(!is) cout << -1 << endl;
}
 
signed main() {
    cin.tie(0) -> sync_with_stdio(false);
    int T = 1;
   	//read(T);
    while (T--) solve();
    return 0;
}

D - Zero Quantity Maximization

 

根据公式 任意x = a[i] * d + b[i]

// Problem: D - Zero Quantity Maximization
// Contest: Virtual Judge - 22练习赛
// URL: https://vjudge.net/contest/578163#problem/D
// Memory Limit: 256 MB
// Time Limit: 2000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#include<iostream>
#include<algorithm>
#include<vector>
#include<set>
#include<queue>
#include<map>
#include<string>
#include<cstring>
#include<cmath>
#include<bitset>
#include<sstream>//切割strtream头文件
#include<climits>//INT_MAX文件
#include <utility>
#include<memory>//for unique_ptr shared_ptr
using i64 = int64_t;
using namespace std;
#define int i64
#define endl '\n'
#define AC return 0;
#define WA(x) cout << x << endl;
#define lowbit(x) x & -x
const int maxn = 1e6 + 10;
const int mod = 1e9 + 7;
int n, m, k, d, T = 1, A, B;

template<typename T>void read(T &x) {
    T f = 1;x = 0;char s = getchar();
    while(s < '0' || s > '9') {if(s == '-')f = -1;s = getchar();}
    while(s >= '0' && s <= '9') {x = x * 10 + s - '0';s = getchar();}
    x *= f;
}

template<typename T>void print(T x) {
    if(x < 0) putchar('-'),x = -x;
    if(x > 9) print(x / 10);
    putchar(x % 10 + '0');
    putchar('\n');
}
constexpr int Init(int x)
{
	return x * 2;
}
int a[maxn], b[maxn];
map<long double,int>Mod;
void solve()
{
	auto x = make_unique<int>();
	cin >> n;
	int z = 0;
	// c - b[i] = a[i] * d
	// 令 c = 0
	// d = -b[i] / a[i] ==>> 出现最多的d的次数 + 一定为0的个数即 a[i] == b[i] == 0
	for(int i = 1;i <= n;i++)cin >> a[i];
	for(int i = 1;i <= n;i++)cin >> b[i];
	for(int i = 1;i <= n;i++)
	{
		if(a[i] == 0){z += (b[i] == 0);continue;}
		Mod[(long double)-b[i] / a[i]]++;
	}
	int ans = 0;
	for(auto x : Mod)
	ans = max(ans, x.second);
	cout << ans + z << endl;
}
 
signed main() {
    cin.tie(0) -> sync_with_stdio(false);
    int T = 1;
   	//read(T);
    while (T--) solve();
    return 0;
}

 E - Banh-mi

 根据题意可以知道一个情况

每次吃xi ,其余 + xi,若xi == 0则sum最终为0(x1 = 0 | 1)

 那么贪心的将,希望sum最大,我们希望 + xi最大,每次吃掉的xi就为最大

统计1的个数,若1的个数为0 == >> ans = 0

else

对于1的变化一定为 1 2 4 8 ……(每次吃最大,第一次一定吃1,则最大变为2,吃2,变为4……)

num1 个 1的贡献等于 pow(2,num1) - 1

对于num0 个0 前num1个操作使得此时的0变成pow(2,num1) - 1

num0个操作后面0的贡献为(pow(2,num1) - 1) * (pow(2,num0) - 1)

ans = pow(2,num1) - 1 + (pow(2,num1) - 1) * (pow(2,num0) - 1)  = (pow(2,num1) - 1) * (pow(2,num0) )

我们用线段树维护区间[l,r]中间1的个数(写完发现前缀和即可,看到区间就想线段树了%……) 

// Problem: E - Banh-mi
// Contest: Virtual Judge - 22练习赛
// URL: https://vjudge.net/contest/578163#problem/E
// Memory Limit: 256 MB
// Time Limit: 1000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#include<iostream>
#include<algorithm>
#include<vector>
#include<set>
#include<queue>
#include<map>
#include<string>
#include<cstring>
#include<cmath>
#include<bitset>
#include<sstream>//切割strtream头文件
#include<climits>//INT_MAX文件
#include <utility>
#include<memory>//for unique_ptr shared_ptr
using i64 = int64_t;
using namespace std;
#define int i64
#define endl '\n'
#define AC return 0;
#define WA(x) cout << x << endl;
#define lowbit(x) x & -x
const int maxn = 1e6 + 10;
const int mod = 1e9 + 7;
int n, m, k, d, T = 1, A, B;

template<typename T>void read(T &x) {
    T f = 1;x = 0;char s = getchar();
    while(s < '0' || s > '9') {if(s == '-')f = -1;s = getchar();}
    while(s >= '0' && s <= '9') {x = x * 10 + s - '0';s = getchar();}
    x *= f;
}

template<typename T>void print(T x) {
    if(x < 0) putchar('-'),x = -x;
    if(x > 9) print(x / 10);
    putchar(x % 10 + '0');
    putchar('\n');
}
constexpr int Init(int x)
{
	return x * 2;
}
string s;
struct node
{
	int l, r, w;
}tr[maxn];

void pushup(int u)
{
	tr[u].w = tr[u << 1].w + tr[u << 1 | 1].w;
}

int mypow(int a, int n)
{
	int ans = 1;
	while (n)
	{
		if (n & 1)
		{
			n -= 1;
			ans = ans * a % mod;
		}
		else
		{
			n /= 2;
			a = a * a % mod;
		}
	}
	return ans;
}

void built(int u, int l, int r)
{
	tr[u] = {l, r};
	if(l == r)tr[u].w = (s[l] == '1');
	else
	{
		int mid = (l + r) >> 1;
		built(u << 1,l, mid);
		built(u << 1 | 1,mid + 1, r);
		pushup(u);
	}
}

int query(int u ,int l, int r)
{
	if(tr[u].l >= l && tr[u].r <= r)return tr[u].w;
	int mid = (tr[u].l + tr[u].r) >> 1;
	int res = 0;
	if(l <= mid)res += query(u << 1, l, r);
	if(r > mid)res += query(u << 1 | 1, l, r);
	return res;
}

void solve()
{
	auto x = make_unique<int>();
	cin >> n >> m >> s;
	s = "*" + s;
	built(1, 1, n);
	//cout  << tr[1].l << " " << tr[1].r << " " << tr[1].w << endl;
	while(m--)
	{
		int l, r;
		cin >> l >> r;
		int num1 = query(1, l, r);
		int num0 = (r - l + 1) - num1;
		if(num1 == 0)cout << 0 << endl;
		else
		{
			int ans = (mypow(2, num1) - 1) * mypow(2, num0);
			cout << ans % mod << endl;
		}
	}
}
 
signed main() {
    cin.tie(0) -> sync_with_stdio(false);
    int T = 1;
   	//read(T);
    while (T--) solve();
    return 0;
}

F - The Number Of Good Substrings

 

 

首先暴力先行 

 枚举1到n的数字

将数字转换为二进制串

if(t.size() > n)break;后续不可能出现 == 的情况

else k = i - t.size();//前补0

只需要查找s中间t出现的次数累加即可

// Problem: F - The Number Of Good Substrings
// Contest: Virtual Judge - 22练习赛
// URL: https://vjudge.net/contest/578163#problem/F
// Memory Limit: 256 MB
// Time Limit: 4000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#include<iostream>
#include<algorithm>
#include<vector>
#include<set>
#include<queue>
#include<map>
#include<string>
#include<cstring>
#include<cmath>
#include<bitset>
#include<sstream>//切割strtream头文件
#include<climits>//INT_MAX文件
#include <utility>
#include<memory>//for unique_ptr shared_ptr
using i64 = int64_t;
using namespace std;
#define int i64
#define endl '\n'
#define AC return 0;
#define WA(x) cout << x << endl;
#define lowbit(x) x & -x
const int maxn = 1e6 + 10;
const int mod = 1e9 + 7;
int n, m, k, d, T = 1, A, B;

template<typename T>void read(T &x) {
    T f = 1;x = 0;char s = getchar();
    while(s < '0' || s > '9') {if(s == '-')f = -1;s = getchar();}
    while(s >= '0' && s <= '9') {x = x * 10 + s - '0';s = getchar();}
    x *= f;
}

template<typename T>void print(T x) {
    if(x < 0) putchar('-'),x = -x;
    if(x > 9) print(x / 10);
    putchar(x % 10 + '0');
    putchar('\n');
}

constexpr int Init(int x)
{
	return x * 2;
}

int check(const std::string& s, const std::string& t) {
	int count = 0;
    size_t pos = s.find(t);
    while (pos != std::string::npos) {
        count++;
        pos = s.find(t, pos + 1);
    }
    return count;
}

void solve()
{
	auto x = make_unique<int>();
	string s;
	cin >> s;
	int n = s.size();
	int ans = 0;
	for(int i = 1;i <= n; i++)
	{
		string t = bitset<32>(i).to_string();
		t = t.substr(t.find('1'));
		if(t.size() > i)break;
		if(t.size() < i)
		{
			int k = i - t.size();
			for(int j = 1;j <= k;j++)
			t = "0" + t;
		}
		//cout << i  << " " << t << endl;
		ans += check(s, t);
	}
	cout << ans << endl;
}
 
signed main() {
    cin.tie(0) -> sync_with_stdio(false);
    int T = 1;
  	cin >> T;
    while (T--) solve();
    return 0;
}

然后 很愉快的TIL

不难想 二进制下出现0(前往后)数字num的变化 == num << 1 = num * 2

若出现1(再末尾)num += 1

从前往后枚举(0 -> n)

∵前置0对num没有任何作用

∴我们直接先跳到距离i最近的1的位置(用a[i]保存)

 和先前讲解的一样若次数 num == j(尾) - i(头) + 1满足答案条件ans++

若 > break;

// Problem: F - The Number Of Good Substrings
// Contest: Virtual Judge - 22练习赛
// URL: https://vjudge.net/contest/578163#problem/F
// Memory Limit: 256 MB
// Time Limit: 4000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#include<iostream>
#include<algorithm>
#include<vector>
#include<set>
#include<queue>
#include<map>
#include<string>
#include<cstring>
#include<cmath>
#include<bitset>
#include<sstream>//切割strtream头文件
#include<climits>//INT_MAX文件
#include <utility>
#include<memory>//for unique_ptr shared_ptr
using i64 = int64_t;
using namespace std;
#define int i64
#define endl '\n'
#define AC return 0;
#define WA(x) cout << x << endl;
#define lowbit(x) x & -x
const int maxn = 1e6 + 10;
const int mod = 1e9 + 7;
int n, m, k, d, T = 1, A, B;

template<typename T>void read(T &x) {
    T f = 1;x = 0;char s = getchar();
    while(s < '0' || s > '9') {if(s == '-')f = -1;s = getchar();}
    while(s >= '0' && s <= '9') {x = x * 10 + s - '0';s = getchar();}
    x *= f;
}

template<typename T>void print(T x) {
    if(x < 0) putchar('-'),x = -x;
    if(x > 9) print(x / 10);
    putchar(x % 10 + '0');
    putchar('\n');
}

constexpr int Init(int x)
{
	return x * 2;
}
int a[maxn];//记录最近的一个1
void solve()
{
	string s;
	cin >> s;
    int n = s.size(), pre = n;
    int ans = 0;
    for(int i = n - 1;i >= 0;i--)
    {
    	if(s[i] == '1')
    	pre = i;
    	a[i] = pre;
    }
    for(int i = 0; i < n;i++)
    {
    	int num = 0;
    	for(int j = a[i];j < n;j++)
    	{
    		num *= 2;
    		if(s[j] == '1')num++;
    		if(num == j - i + 1)ans++;`
    		if(num > n) break;
    	}
    }
    cout << ans << endl;
}

signed main() {
    cin.tie(0) -> sync_with_stdio(false);
    int T = 1;
  	cin >> T;
    while (T--) solve();
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值