1. 程式人生 > >沈陽集訓day2

沈陽集訓day2

題解 暴力匹配 參數 bool esp 解決 div include tag

問題 A: 置換

題目描述

negii就是我們要將7(0111)翻轉成14(1110),11(1011)翻轉成13(1101)。

現在我們給定二進制位數k以及n個滿足二進制位數不超過k的數,我們需要輸出對應翻轉後的數的十進制表示

由於讀入量較大,所以n個數由本機隨機生成,具體生成方式如下

int my_rand()

{

Seed=(214013LL*Seed+2531011)&((1<<k)-1);

return Seed;

}

我們會給出初始的Seed,我們會調用n次函數,得到需要翻轉的n個數

我們還會采取特殊的輸出方式,我們將所有答案hash,並輸出最後的值即可

int ans=0;

void my_hash(int x)

{

ans=((long long)ans*233+x)%99824353;

}

我們每得到一個數,進行翻轉後,我們就會調用一次這個函數,其中傳入參數x為翻轉後的數,我們最後輸出ans的值即可。

輸入

共3個數,分為n,k,Seed

輸出

一行,一個整數,表示最後hash值。

樣例輸入

5 3 233

樣例輸出

76005766

提示

數據範圍


對於前50% k<=17


對於前70% k<=20


對於前90% k<=23


對於 100% n<=2k ,k<=25

題解:暴力hash

技術分享圖片
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1<<25;
int n, k, Seed;
int p[maxn+1];
int my_rand()
{
    Seed=(214013LL*Seed+2531011)&((1<<k)-1);
    return Seed;
}
 
int ans=0;
 
void my_hash(int x)
{
    ans=((long long)ans*233+x)%99824353;
}
int main(){
     
    scanf(
"%d%d%d", &n, &k, &Seed); p[0] = 0; for(int i = 1; i <= (1<<25); i++){ int c = p[i>>1]; p[i] = (c>>1) | ( (i&1) << (k-1) ); } for(int i = 1; i <= n; i++){ int now = my_rand(); my_hash(p[now]); } printf("%d\n",ans); }
View Code

問題 B: 字符串

題目描述

negii和 starria 是好朋友。他們在一起做字符串遊戲。

我們定義對於一個字符串的翻轉操作:比如翻轉的串為 R,那麽他會將前|R|?1個字符倒序後,插入到該串的最後。舉個例子,串abd進行翻轉操作後,將得到abdba

negii進行了若幹次(可能為 0 次)字符串的翻轉操作。

negii對starria展示出了一個非空串S, S 是一個串 R 的前綴。他想考考starria,初始的串 R 的長度可能是多少。

starria找到了正在參加模擬賽的你,請你來幫她解決這個問題。但聰明的starria發現,所有超過 |S| 的整數都一定是 R 的可能長度,因此你只需要告訴她不超過的 |S| 的 R 的可能長度即可。

輸入

輸入包含多組數據,第一行一個整數 T 表示數據組數。

接下來依次描述每組數據,對於每組數據,一行一個僅由小寫字母組成的非空字符串S。

輸出

對於每組數據,輸出 1 行,從小到大輸出|R|的所有不超過 |S| 的可能值,所有值之間用單個空格隔開。

樣例輸入

3
abcdcb
qwqwq
qaqaqqq

樣例輸出

4 6
2 3 4 5
6 7

提示

數據範圍


對於40% 保證 ∑|S|≤5×10^2?? 。


對於60% 保證 ∑|S|≤5×10^3?? 。


對於100% 保證 |S|≤106,∑|S|≤5×10^6?? 。

題解:hash暴力匹配前後翻轉的,找開始結束的O1查詢; 或者馬拉車,但是我寫掛了

hash

技術分享圖片
#include<bits/stdc++.h>
using namespace std;
const  int maxn = 1000005, bas = 233;
bool vis[maxn], tag[maxn];
int sh, len, base[maxn], hs1[maxn], hs2[maxn];
char s[maxn], str[maxn];
bool gethash(int l, int ed){
    int a = hs1[ed] - hs1[ed-l]*base[l], b = hs2[len-ed+1] - hs2[len-ed+1-l]*base[l];
    return a == b;
}
int cmp(int ed){
    int l1 = ed, l2 = len - ed + 1;
    if(l1 >= l2)
        if(gethash(l2, ed))return 1;
        else return -1;
     
    if(l1 < l2)
        if(gethash(l1, ed)){
            sh = ed + l1 - 1;
            return 0;
        }
        else return -1;
     
}
bool dfs(int k){
    if(vis[k])return tag[k];
    vis[k] = 1;
    int pp = cmp(k);
    if( pp < 0)return tag[k] = 0;
    if( pp == 0)return tag[k] = dfs(sh);
    else return tag[k] = 1;
}
void init(){
    base[0] = 1;
    for(int i = 1; i <= len; i++)
        base[i] = base[i- 1] * bas , hs1[i] = hs1[i-1] * bas + s[i-1] - a ;
    for(int i = 1; i <= len; i++)
        hs2[i] = hs2[i-1] * bas + s[len - i] - a;
     
}
int main(){
    int T;
    scanf("%d",&T);
    while(T--){
        scanf("%s", s);
        len = strlen(s);
        init();
         
        memset(vis, 0, sizeof(vis));
        memset(tag, 0, sizeof(tag));
        tag[len] = 1;
        for(int i = 2; i < len; i++)
            if(!vis[i])dfs(i);
        for(int i = 1; i <= len; i++)
            if(tag[i])printf("%d ", i);
        printf("\n");
    }
}
View Code

manacher

技術分享圖片
#include<bits/stdc++.h>
using namespace std;
const  int maxn = 1000005;
bool vis[maxn], tag[maxn];
int sh, len, p[maxn<<1];
char s[maxn], str[maxn<<1];
int cmp(int ed){
    int l1 = ed + 1, l2 = len - ed;
    if(l1 >= l2)
        if( p[ed*2+2]/2 >= l2 )return 1;
        else return -1;
     
    if(l1 < l2){
        int ll = p[ed*2+2]/2;
        if(ll < l1)return -1;
        sh = ed + ll - 1;
        return 0;
    }
 
     
}
 
void manacher(){
    memset(p, 0, sizeof(p));
    str[0] = $;
    str[1] = #;
    int len1 = strlen(s);
    for(int i = 0; i < len1; i++){
        str[i*2 + 2] = s[i];
        str[i*2 + 3] = #;
    }  
    int len2 = len1*2 + 2;
    int id = 0, maxid = 0; 
    for( int i = 1; i <= len2; i++){
        if(maxid > i)
            p[i] = min(p[id*2 - i], maxid - i);
        else p[i] = 1;
        while(str[i - p[i]] == str[i + p[i]])p[i]++;
        if( p[i] + i > maxid){
            id = i;
            maxid = i + p[i];
        }
    }
}
bool dfs(int k){
    if(vis[k])return tag[k];
    vis[k] = 1;
    int pp = cmp(k);
    if( pp < 0)return tag[k] = 0;
    if( pp == 0)return tag[k] = dfs(sh);
    else return tag[k] = 1;
}
int main(){
    int T;
    scanf("%d",&T);
    while(T--){
        scanf("%s", s);
        len = strlen(s);
        manacher();
        memset(vis, 0, sizeof(vis));
        memset(tag, 0, sizeof(tag));
        tag[len-1] = 1;
        for(int i = 1; i < len; i++)
            if(!vis[i])dfs(i);
        for(int i = 0; i < len; i++)
            if(tag[i])printf("%d ", i+1);
        printf("\n");
    }
}
View Code

問題 C: 女神

題目描述

技術分享圖片

輸入

共一行,一個正整數n

輸出

一個整數,為答案除以1e9+7的余數

樣例輸入

520

樣例輸出

563343175

提示

數據範圍


20 % : n<=300


40 % : n<=2,000


50 % : n<=10,000


70 % : n<=1,000,000


100 % : n<=1,000,000,000

題解:數學題, 遞推公式:ans = n * (n + 1) ^ (n - 2) ;

技術分享圖片
#include<bits/stdc++.h>
using namespace std;
const  int maxn = 10005;
#define ll long long 
const ll p = 1e9+7;
ll pow(ll n){
    ll ans = 1, a = 2;
    for(; n; n>>=1, a = a*a %p)
        if(n & 1)ans = ans*a% p;
    return ans;
}
int main(){
    ll n;
    cin>>n;
    ll ans = n * (n + 1) % p * pow(n - 2) % p;      
    cout<<ans<<endl;
}
View Code

沈陽集訓day2