uoj #297. 【CTSC2017】密鑰

#297. 【CTSC2017】密鑰

一個密鑰是一個長度爲 n=2k+1n=2k+1 的字符串,它包含 11 個字母X、kk 個字母 A 和 kk 個字母 B。例如 k=3k=3 時,BAXABAB 就是一個密鑰。ios

以下圖所示,能夠按順時針順序把這 2k+12k+1 個字母排成一個圈:數組

圈

kk 個字母 A 中,有一部分能夠定義爲"強的"。ide

具體來講,從 X 出發順時針走到某個 A 時,若是途中 A 的數目嚴格多於 B 的數目,則稱此字母 A 爲強的。測試

對於上面的例子來講,順時針方向從字母 X 數起第 11 個和第 22 個字母 A 是強的,而第 33 個字母 A 不是強的。atom

一個密鑰的特徵值就是其中包含的強的字母 A 的個數。spa

天才小朋友 KT 給出了一個結論:code

假設 kk 個字母 A 所在的位置已經固定,可是剩下的 kk 個 B 和 11 個 X 的位置是未知的。 (注意,知足這樣要求的密鑰一共有 k+1k+1 個,由於字母 X 還剩下 k+1k+1 個可能的位置。)orm

能夠證實:全部這k+1k+1個可能的密鑰的特徵值是各不相同的,它們剛好爲0,1,2,,k0,1,2,…,k。xml

下頁的圖是一個具體的示例,從左到右的四個子圖中分別有3個,2個,1個,0個字母A是強的。blog

圈

相似地,若是固定 kk 個字母 B 的位置,那知足條件的全部 k+1k+1 個密鑰的特徵值也各不相同,剛好爲 0,1,,k0,1,⋯,k。

如今你須要解決如下三個問題:

  1. 給定密鑰中全部 A 的位置,當密鑰的特徵值爲 00 時,請問 X 在哪一個位置。
  2. 給定密鑰中全部 A 的位置,當密鑰的特徵值爲 SS 時,請問 X 在哪一個位置。
  3. 給定密鑰中全部 B 的位置,當密鑰的特徵值爲 SS 時,請問 X 在哪一個位置。

注意:字符串的 2k+12k+1 個字母的位置由 11 到 2k+12k+1 編號。

例子一

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

當 A 的位置是 {2,4,6}{2,4,6} 且特徵值爲 00 時,X 的位置在 77;

當 A 的位置是 {2,4,6}{2,4,6} 且特徵值爲 22 時,X 的位置在 33;

當 B 的位置是 {2,4,6}{2,4,6} 且特徵值爲 22 時,X 的位置在 55。

例子二

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

當 A 的位置是 {3,4,5,9,10,12,13,16,19}{3,4,5,9,10,12,13,16,19} 且特徵值爲 00 時,X 的位置在 1414;

當 A 的位置是 {3,4,5,9,10,12,13,16,19}{3,4,5,9,10,12,13,16,19} 且特徵值爲 77 時,X 的位置在 1818;

當 B 的位置是 {3,4,5,9,10,12,13,16,19}{3,4,5,9,10,12,13,16,19} 且特徵值爲 77 時,X 的位置在 1717。

輸入格式

只包含一組測試數據。

第一行包含一個整數kk,意義如題所述。

第二行包含一個整數seedseed,這個數將用於生成一個kk元集合P。

第三行包含一個整數SS,意義如題所述。

保證0Sk1070≤S≤k≤107。1seed100001≤seed≤10000。

在下發文件中,包含三個用於生成輸入數據的文件cipher.cpp/c/pas。其中讀入部分已經完成,在數組 p[]p[] 中,若 p[i]=0p[i]=0,表示 ii 不屬於集合PP,不然,ii 屬於集合 PP。

輸出格式

輸出三行,每行一個數,依次對應問題描述中的三個子問題的答案。

即:

  1. 第一個數表示當 kk 元集合 PP 表明 A 的位置且特徵值爲 00 時 X 的位置。
  2. 第二個數表示當 kk 元集合 PP 表明 A 的位置且特徵值爲 SS 時 X 的位置。
  3. 第三個數表示當 kk 元集合 PP 表明 B 的位置且特徵值爲 SS 時 X 的位置。

樣例一

input

5
3344
2

output

10
1
2

explanation

第一個樣例中,PP 數組爲 11 的元素的下標分別爲 5,6,7,8,95,6,7,8,9。

樣例二

input

500000
4545
234567

output

999992
246922
753067

限制與約定

對於 30%30% 的數據,k103k≤103。

對於 50%50% 的數據,k105k≤105。

對於 100%100% 的數據,k107k≤107。

對於每一個測試點,得分爲如下三部分得分之和:

  1. 若是第一問回答正確,你將得到 33 分。
  2. 若是第二問回答正確,你將得到 44 分。
  3. 若是第三問回答正確,你將得到 33 分。

若是你僅僅知道部分答案,請也務必按此格式要求輸出三個數。不然你可能會因格式錯誤沒法得分。

時間限制:1s1s

空間限制:512MB

 

 

#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分 暴力
相關文章
相關標籤/搜索