• 沈阳集训day2


    问题 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
    ",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("
    ");
        }
    }
    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("
    ");
        }
    }
    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
  • 相关阅读:
    [改善Java代码]在equals中使用getClass进行类型判断
    [改善Java代码]equals应该考虑null值的情景
    [改善Java代码]覆写equals方法时不要识别不出自己
    [改善Java代码] 推荐使用序列化实现对象的拷贝
    [改善Java代码]避免对象的浅拷贝
    [改善Java代码]让工具类不可实例化
    [改善Java代码]建议40:匿名类的构造函数很特殊
    [改善Java代码]使用匿名类的构造函数
    [改善Java代码]使用静态内部类提高封装性
    [改善Java代码]构造函数尽量简化
  • 原文地址:https://www.cnblogs.com/EdSheeran/p/9275199.html
Copyright © 2020-2023  润新知