ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Codeforces Round #735 (Div. 2)题解

2021-07-30 17:58:39  阅读:204  来源: 互联网

标签:cout int 题解 ++ cin -- 异或 735 Div


       这一场div2主要偏向于公式的推导对于时间复杂度的优化。这要求我们对于生活中的一些数字图案具有一定的敏感度。

       题目中给了我们许多的提示,比如1e5的数据量,如果我们采取逐个配对的方法,那么时间复杂度一定会超时。再考虑到各种数据结构的嵌套中,并没有一种适合的方法。此时,我们的思考方向就要偏向于规律、化简。我们不妨对于数据进行枚举来寻找其中的规律。

在这里插入图片描述
在这里插入图片描述题目大意
给定n个数字组成的数字(n的范围为(2,1e5))。每一个数字大小为(1,1e6)之间。问任一大于2的区间段内所有数字组成的集合的最大值与最小值的乘积的最大值

解题思路
这是一个非常经典的规律总结题。从最平凡的入手,我们会发现求出所有的区间段的值,它的时间复杂度为O(1e10)。首先,我考虑到dp动态规划的推导。那么要求出所有的区间段用(l,r)来维护,显然时间复杂度并没有优化。此时,我们不妨贪心的去思考这个问题,我们能否从最大处开始枚举,答案也是否定的。最后,在各种方法的试探之下,并没有一个符合的解决办法。那么,我们从规律入手,会发现对于三个数来说,我们会发现f(1,3)永远小于max(f(1,2),f(2,3))。我们会发现数组合并时,最小值的大小永远不会增加。

代码

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

#define debug(a) cout << #a << ": " << a << endl;
#define LL long long 
#define IO ios::sync_with_stdio(0),cin.tie(0),cout.tie(0)
const int maxn = 1e5+10;
int a[maxn];

void solve()
{
    int n;
    cin >> n;
    for(int i = 1;i <= n;++i) {
        cin >> a[i];
    }
    LL ans = 0;
    for(int i = 2;i <= n;++i) {
        ans = max(ans,a[i]*1ll*a[i-1]);
    }
    cout << ans << endl;
}

int main()
{
    IO;
    int t;
    cin >> t;
    while(t--){
        solve();
    }
    return 0;
}

题目总结
这是一个非常常见的规律总结题。近似于短板效应,要建立一个长盛不衰的知识体系,就要不断学习巩固所学知识。而不是各方面都留有漏洞,多学不如精学。

在这里插入图片描述

在这里插入图片描述
题目大意
给定一个长度为n的数组和一个整数k。求出任意数对(i,j)i!=j满足ij-k(ai*aj)取得最大值。n的范围(2,1e5),k的范围min(n,100),ai的范围(1,n)

解题思路
我们希望取得最大值,那么我们不妨取i=n-1,j=n;我们可以发现f(n-1,n)的最小值为n^2-2kn-n,而f(i,n)的最大值为in。要使f(i,n)大于f(n-1,n)那么i的范围需要大于n-2k。由此可化简时间复杂度为O(1e7)

代码

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

#define debug(a) cout << #a << ": " << a << endl;
#define LL long long 
#define IO ios::sync_with_stdio(0),cin.tie(0),cout.tie(0)
const int maxn = 1e5+10;
int a[maxn];


void solve()
{
    int n,k;
	cin >> n >> k;
	for(int i = 1;i <= n;++i) {
		cin >> a[i];
	}
	int l = max(1,n-200);
	LL ans = -1*1e18;
	for(int i = l;i < n;++i) {
		for(int j = i+1;j <= n;++j) {
			ans = max(ans,i*1ll*j-1ll*k*(a[i] | a[j]));
		}
	}
	cout << ans << endl;
}

int main()
{
    IO;
    int t;
    cin >> t;
    while(t--){
        solve();
    }
    return 0;
}

题目总结
一道比较经典的规律总结题,难度不高,很考验思维。但也给了相关提示。

在这里插入图片描述在这里插入图片描述题目大意
有t组样例,t的范围(1,3e4)
每组样例,给定n,m两个数,它们的范围为(1,1e9)
从n异或0,n异或1,······,n异或m。
求这些数组成的数组中第一个没有出现的最小的自然数的值。

解题思路
我们不妨从另一个角度思考,a异或b等于c。那么a异或c也就等于b。从这个角度出发,我们可以发现a如果异或一个值小于b。那么a通过异或就可以得到那个值。题目转变为求出最小的值使得a与其异或的值大于等于m+1

代码

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

#define debug(a) cout << #a << ": " << a << endl;
#define LL long long 
#define IO ios::sync_with_stdio(0),cin.tie(0),cout.tie(0)

void solve()
{
    int n,m;
    cin >> n >> m;
    ++m;
    int ans = 0;
    for(int k = 30;k >= 0;k--) {
        if((n>>k&1) == (m>>k&1)) continue;
        else if((n>>k&1) == 1) break;
        else ans |= (1<<k);
    }
    cout << ans << endl;
}

int main()
{
    IO;
    int t;
    cin >> t;
    while(t--){
        solve();
    }
    return 0;
}

题目总结
异或,我们不妨首先就考虑所有数字的二进制呈现形式。

在这里插入图片描述在这里插入图片描述题目大意
构造一个字符串,使得字符串中的每一个子串出现的次数都为奇数。

解题思路
为了使每一个子串出现的次数都为奇数,我们尽可能采用少量的字符串。通过实验证明了方法的可行性,见代码。

代码

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

#define debug(a) cout << #a << ": " << a << endl;
#define LL long long 
#define IO ios::sync_with_stdio(0),cin.tie(0),cout.tie(0)

int main()
{
    IO;
    int t;
    cin >> t;
    while(t--){
         int n;
         cin >> n;
         if(n == 1) {
            cout << 'a';
         }
         else if(n%2 == 0) {
            for(int i = 0;i < n/2;++i) cout << 'a';
            cout << 'b';
            for(int i = 0;i < n/2-1;++i) cout << 'a';
         }
         else {
            for(int i = 0;i <= n/2-1;++i) cout << 'a';
            cout << 'b' << 'c';
            for(int i = 0;i < n/2-1;++i) cout << 'a';
         }
         cout << endl;
    }
    return 0;
}

题目总结
字符串构造,第一,尽量采用少量的字符串;第二,大规模地数据构造体验。

在这里插入图片描述在这里插入图片描述题目概括
一种抽象化的剪枝,达到优化时间复杂度的目的。

代码

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

#define debug(a) cout << #a << ": " << a << endl;
#define LL long long 
#define IO ios::sync_with_stdio(0),cin.tie(0),cout.tie(0)
const int maxn = 1e5+10,mod = 998244353;
int ans[maxn];
vector<vector<int>> ej(maxn);
int eo[maxn];
int sz[maxn];

void dfs(int p, int i) {
	int o;
	sz[i] = 1;
	for (o = eo[i]; o--; ) {
		int j = ej[i][o];
		if (j != p) {
			dfs(i, j);
			sz[i] += sz[j];
		}
	}
}

void solve()
{
    int n;
    cin >> n;
    for(int i = 0;i < n;++i) eo[i] = 0;
    for(int i = 0;i < n-1;++i) {
        int x,y;
        cin >> x >> y;
        x--,y--;
        eo[x]++;
        ej[x].push_back(y);
        eo[y]++;
        ej[y].push_back(x);
    }
    for(int i = 0;i <= n+5;++i) ans[i] = 0;
    ans[1] = 1;
    for(int i = 0;i < n-1;++i) 
        ans[1] = ans[1]*2%mod;
    dfs(-1,0);
    for (int i = 2;i <= n;i++)
    if ((sz[0] - 1) % i == 0) {
        int good = 1;
        for (int j = 1;j < n;j++)
            if (sz[j] % i > 1) {
                good = 0;
                break;
            }
        if (good)
            ans[i]++;
    }
    for (int i = n;i >= 1;i--)
        for (int j = i + i;j <= n;j += i)
            ans[i] = (ans[i] - ans[j] + mod) % mod;
    for (int i = 1; i <= n; i++)
        cout << ans[i] << ' ';
    cout << endl;
    for(int i = 0;i < n+5;++i) {
        ej[i].clear();
    }
    return ;
}

int main()
{
    IO;
    int t;
    cin >> t;
    while(t--){
        solve();
    }
    return 0;
}

标签:cout,int,题解,++,cin,--,异或,735,Div
来源: https://blog.csdn.net/yundan12/article/details/119251919

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有