Codeforces Round #735 (Div. 2)

Codeforces Round #735 Div. 2

  • A. Cherry
  • B. Cobb
  • C. Mikasa
  • D. Diane

很废,做了一题。
第二题超时了,删掉一个0就给多了,血亏
做题地址:Codeforces Round #735 Div.2

A. Cherry

题目:
让连续区间内,最大值和最小值的乘积最大

解决:
可以看出相邻两个的最大乘积就是答案。

分析:
假设最优答案至少是长度为3的连续区间,那么,长度为3的连续区间内,有一个最大值,一个最小值,和一个中等值,那么,相邻两个的乘积要么最大,要么次大,但一定可以覆盖长度为3的区间的答案,甚至更优。

代码:

int n;
LL a[N];
void work()
{
  cin >> n;
  for (int i = 1; i <= n; i ++ )
    scanf("%lld", &a[i]);
  LL ans = 0;
  for (int i = 2; i <= n; i ++ )
    ans = max(ans, a[i] * a[i - 1]);
  printf("%lld\n", ans);
} 

B. Cobb

题目:
给定一个长度为n的序列,输出i * j - k * (a[i] | a[j])的最大值。

解决:
我们知道n是1e5大小的数字,k是个小于100的数字,而且a[i] | a[j]最大不过2 * n大小,所以,当n比较小的时候,可以暴力做。当n大的时候可以只枚举后100个就可以了

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
//#pragma GCC optimize(2)
//#pragma GCC optimize(3, "Ofast", "inline")

using namespace std;

#define ios ios::sync_with_stdio(false) , cin.tie(0),cout.tie(0)
#define rep(i, n) for (int i = 0; i < n; ++ i)
#define x first
#define y second

typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int, int> PII;

const int N = 300010, INF = 0x3f3f3f3f, mod = 1e9 + 7, base = 131;
const double eps = 1e-6, PI = acos(-1);

LL n, k;
LL a[N];
void work()
{
  memset(a, 0, sizeof a);
  cin >> n >> k;
  for (int i = 1; i <= n; i ++ )
    scanf("%lld", &a[i]);
  if (n <= 1000)
  {
    LL ans = -2e14;
    for (LL i = 1; i <= n - 1; i ++ )
      for (LL j = i + 1; j <= n; j ++ )
        ans = max(ans, i * j - k * (a[i] | a[j]));
    printf("%lld\n", ans);
  }
  else
  {
    LL ans = -2e14;    
    for (LL j = n - 100; j <= n; j ++ )
    for (LL i = 1; i < j; i ++ )
      ans = max(ans, j * i - k * (a[i] | a[j]));
    printf("%lld\n", ans);
  }
}

int main(void)
{
  //ios;
  int T = 1;
  cin >> T;
  while (T -- )
  {
    work();
  }

  return 0;
}

C. Mikasa

题目:给定n和m,都是1e9大的数字,问{n ^ 0 , n ^ 1, …, n ^ m}中,最小的没有出现的非负整数为多少。

解决:
首先,我们需要了解一个性质:
a ^ x = y, 等价于 a ^ y = x
明白这个性质后,我们再观察{n ^ 0 , n ^ 1, …, n ^ m}。
假定n ^ x = k,我们要找的就是不在序列中出现过的最小非负整数k。
那么,我们交换x和k,n ^ k = x,可以发现,所有的k值的集合,一定满足,n ^ k 的值x是连续的从0到n。一定不满足n ^ k > m。
所以,我们需要找到的就是n ^ k > m中,最小的k。

如果不理解的话,可以换一个角度来考虑。
我们依次考虑k = 0,k = 1,k = 2,k = …。如果n ^ k 在0~m的范围内,那么,一定存在n ^ (0 ~ m) = k。这样的k都是合法的,那么直到第一个k使得n ^ k > m。这时,就不存在{0, 1, … m}和n异或得到这个k。那么,这个k就是我们的合法方案。
不知道这样说清不清楚哎QAQ

#include 
using namespace std;
const int N = 100010;
int n, m;
void work()
{
  cin >> n >> m;
  m ++;
  //也可以先特判下n > m直接为0
  int ans = 0;
  for (int i = 30; i >= 0 && n < m; i -- )
  {
    if ((n >> i & 1) && (m >> i & 1)) continue;
    //我们可以n = n ^ k。当n
    if ((m >> i & 1) && !(n >> i & 1)) ans |= 1 << i, n |= 1 << i;
  }
  cout << ans << endl;
  return;
}
int main()
{
  int T;
  cin >> T;
  while (T -- )
  {
    work();
  }
  return 0;
}

D. Diane

题目:
构造一个1e5的字符串,使得字符串S的每个子串都只出现奇数次。

解决:
假设这里有k个a,那么它的字串个数为a k, aa k - 1, aaa k - 2, …
如果有k-1个a,那么它的子串个数为a k - 1, aa k - 2, aaa k - 3 …
两者加起来,可得: x + (x - 1) = 2 * x - 1是个奇数
所以,我们可以这么构造
现在我们可以将前n / 2个构造为a,将后n / 2 - 1个构造也为a,中间剩下的用b~c来构造,如果n是偶数,用b,如果是偶数用bc

#include 
using namespace std;
int n;
void work()
{
  cin >> n;
  if (n <= 3)
  {
    if (n == 1) cout << "a" << endl;
    else if (n == 2) cout << "ab" << endl;
    else if (n == 3) cout << "abc" << endl;
    return;
  }
  string s(n / 2, 'a');
  string t(n / 2 - 1, 'a');
  if (n & 1) cout << s << "bc" << t << endl;
  else cout << s << "b" << t << endl;
}
int main()
{
  int T; cin >> T;
  while (T -- )
  {
    work();
  }
  return 0;
}

你可能感兴趣的:(Codeforces)