码迷,mamicode.com
首页 > 其他好文 > 详细

沈阳集训day2

时间:2018-07-06 19:42:49      阅读:361      评论:0      收藏:0      [点我收藏+]

标签:while   ons   分享   十进制   scan   lap   get   nbsp   描述   

问题 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

标签:while   ons   分享   十进制   scan   lap   get   nbsp   描述   

原文地址:https://www.cnblogs.com/EdSheeran/p/9275199.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!