一个密钥是一个长度为 k=3 时,BAXABAB 就是一个密钥。

如下图所示,可以按顺时针顺序把这 2k+1 个字母排成一个圈:

uoj #297. 【CTSC2017】密钥

具体来说,从 X 出发顺时针走到某个 A 时,如果途中 A 的数目严格多于 B 的数目,则称此字母 A 为强的。

对于上面的例子来说,顺时针方向从字母 X 数起第 3 个字母 A 不是强的。

一个密钥的特征值就是其中包含的强的字母 A 的个数。

天才小朋友 KT 给出了一个结论:

假设 k+1 个可能的位置。)

可以证明:所有这0,1,2,…,k。

下页的图是一个具体的示例,从左到右的四个子图中分别有3个,2个,1个,0个字母A是强的。

uoj #297. 【CTSC2017】密钥

类似地,如果固定 0,1,⋯,k。

现在你需要解决以下三个问题:

  1. 给定密钥中所有 A 的位置,当密钥的特征值为 0 时,请问 X 在哪个位置。
  2. 给定密钥中所有 A 的位置,当密钥的特征值为 S 时,请问 X 在哪个位置。
  3. 给定密钥中所有 B 的位置,当密钥的特征值为 S 时,请问 X 在哪个位置。

注意:字符串的 2k+1 编号。

例子一

假定 k=3,S=2。那么:

当 A 的位置是 7;

当 A 的位置是 3;

当 B 的位置是 5。

例子二

假定 k=9,S=7。那么:

当 A 的位置是 14;

当 A 的位置是 18;

当 B 的位置是 17。

输入格式

只包含一组测试数据。

第一行包含一个整数k,意义如题所述。

第二行包含一个整数k元集合P。

第三行包含一个整数S,意义如题所述。

保证1≤seed≤10000。

在下发文件中,包含三个用于生成输入数据的文件cipher.cpp/c/pas。其中读入部分已经完成,在数组 P。

输出格式

输出三行,每行一个数,依次对应问题描述中的三个子问题的答案。

即:

  1. 第一个数表示当 0 时 X 的位置。
  2. 第二个数表示当 S 时 X 的位置。
  3. 第三个数表示当 S 时 X 的位置。

样例一

input

5
3344
2

output

10
1
2

explanation

第一个样例中,5,6,7,8,9。

样例二

input

500000
4545
234567

output

999992
246922
753067

限制与约定

对于 k≤103。

对于 k≤105。

对于 k≤107。

对于每个测试点,得分为以下三部分得分之和:

  1. 如果第一问回答正确,你将获得 3 分。
  2. 如果第二问回答正确,你将获得 4 分。
  3. 如果第三问回答正确,你将获得 3 分。

如果你仅仅知道部分答案,请也务必按此格式要求输出三个数。否则你可能会因格式错误无法得分。

时间限制:1s

空间限制:MB

 

 

#include<iostream>
#include<cstdio>
#include<cstring>
#define maxn 20000005
using namespace std;
int p[maxn],b[maxn],cnt,ans[maxn];
int seed, n, k, S;
int getrand()
{
    seed = ((seed * 12321) ^ 9999) % 32768;
    return seed;
}
void generateData()
{
    scanf("%d%d%d",&k,&seed,&S);
    int t = 0;
    n = k * 2 + 1;
    memset(p, 0, sizeof(p));
    for (int i = 1; i <= n; i++)
    {
        p[i] = (getrand() / 128) % 2;
        t += p[i];
    }
    int i = 1;
    while (t > k)
    {
        while (p[i] == 0)
            i++;
        p[i] = 0;
        t--;
    }
    while (t < k)
    {
        while (p[i] == 1)
            i++;
        p[i] = 1;
        t++;
    }
}
int count1(int s){
    int sa=0,sb=0,res=0;
    for(int i=2,j=s+1;i<=n;i++,j++){
        if(p[j]==0)sb++;
        else {
            sa++;
            if(sa>sb)res++;
        }
    }
    return res;
}
void work1(){
    for(int i=1;i<=cnt;i++)//x的位置 
        ans[i]=count1(b[i]);
}
int count2(int s){
    int sa=0,sb=0,res=0;
    for(int i=2,j=s+1;i<=n;i++,j++){
        if(p[j]==1)sb++;
        else {
            sa++;
            if(sa>sb)res++;
        }
    }
    return res;
}
void work2(){
    for(int i=1;i<=cnt;i++)
        ans[i]=count2(b[i]);
}
int main(){
    generateData();
    for(int i=1;i<=n;i++)p[i-1]=p[i];
    for(int i=0;i<n;i++)p[i+n]=p[i];
    for(int i=0;i<n;i++)if(!p[i])b[++cnt]=i;
    if(k<=1000){
        work1();
        int ans0,ans1;
        for(int i=1;i<=cnt;i++){
            if(ans[i]==0)ans0=b[i]+1;
            if(ans[i]==S)ans1=b[i]+1;
        }
        printf("%d\n%d\n",ans0,ans1);
        work2();
        for(int i=1;i<=cnt;i++)
            if(ans[i]==S){
                printf("%d\n",b[i]+1);
                return 0;
            }
    }
    return 0;
}
30分 暴力

相关文章:

  • 2022-12-23
  • 2021-08-24
  • 2022-12-23
  • 2021-11-21
  • 2021-09-03
猜你喜欢
  • 2021-12-12
  • 2021-11-17
  • 2022-12-23
  • 2021-11-05
  • 2021-07-21
  • 2022-12-23
  • 2021-11-17
相关资源
相似解决方案