沈阳集训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\n",ans);
}

问题 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");
    }
}

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");
    }
}

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

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

时间: 2024-10-22 08:24:15

沈阳集训day2的相关文章

长沙雅礼中学集训-------------------day2

怎么说呢,今天的题特别的神奇,因为emmmmmm,T1看不懂(一直到现在还没有理解明白期望概率什么的),T2题面看不懂+扩展欧几里得求逆元怎么求我忘了,T3哇,终于看懂一题了,然而写了个50分的程序但是只拿到了20. day2考试就写了T3,还好写了分段,不然可能就要爆零了(写的是50分的程序,但是很明显我的思路出问题了所以只拿了20分的暴力分) T1:对于一个0/1串,其中一个全为1长度为x的子串会加x^3+k,一个全为0长度为x的子串会减x^2+k,现告诉每个位置为1的概率,求期望的分数.数

FJ省队集训DAY2 T2

思路:我们可以考虑三角剖分,这样问题就变成考虑三角形的选取概率和三角形内有多少个点了. 先用树状数组预处理出三角剖分的三角形中有多少个点,然后用线段树维护,先用原点极角排序,然后枚举i,再以i极角排序,此时线段树的作用就来了,每次到一个询问的教室点,我们就在线段树里面查找之前的概率,统计贡献即可. 1 #include<cstdio> 2 #include<iostream> 3 #include<cmath> 4 #include<cstring> 5 #

FJ省队集训DAY2 T1

思路:转换成n条三维空间的直线,求最大的集合使得两两有交点. 有两种情况:第一种是以某2条直线为平面,这时候只要统计这个平面上有几条斜率不同的直线就可以了 还有一种是全部交于同一点,这个也只要判断就可以了. 然后我并不能改出来,wa了好多个点 WA的程序: 1 #include<cstdio> 2 #include<iostream> 3 #include<cmath> 4 #include<cstring> 5 #include<algorithm&

暑假集训day2

其实这是昨天的事了.(现在时间回到一天前) 今天的主要内容是强连通分量的割点与桥 一下给出割点和桥的写法 #include<cstdio> #include<iostream> #include<cstring> #include<algorithm> #include<vector> #include<map> using namespace std; const int maxn=500010; int dfn[maxn],low

Test 2015.6.26 集训 Day2

今天被四川同学虐场了 Orz 暴力都好难打 T1 题意:给定一棵树和带权值的点,一个价值的计算方式,选取若干条链使得价值最大 正解:转化模型,然后有二分的算法,再加点优化就可以了 题面说树链剖分= =已然被骗,完全没管,然而正解也并没有听太懂 T2 题意:给出一个矩阵和一些障碍点,若在某方格中转弯可以获得一定价值,要求道路要连续,求一个合法的价格最大的价值 正解:转换模型成网络流,直接秒 神一样的转化,然而傻逼的我推的是最短路的模型,直接躺 T3 题意:给出一个 Ai 的计算方式,i,j 范围

2017雅礼集训 Day2

今日得分:60+100+25 = 185,修改后60+100+100 今日题解: T1:有nlogn对不合法的数对,这些数对在DFS序上的支配范围画在平面上是一个或两个矩形,求矩形面积并即可 T2:递推,考虑新增加的一行一列的状态 1.与前面的一行共同完全占据了两行两列,为避免重复我们规定必须选第i列,那么行有C(i,2)种选法,列有i-1种:f[i-2]*C(i,2)*(i-1) 2.没有与前面一行共同占据两行两列,那么相当于把冲突的其中一个位置换到最后一列去:f[i-1]*C(i,2)*2

2014 清华集训 day2

T1-------------------------------------------------------------------------------------------- 简单回路 Description 在一个有障碍点的 n 行 m 列的网格图中,我们用 (x,y) 来表示第 x 行第 y 列的格子.如果该网格图中的回路满足下面两个条件: 不经过任何一个障碍点 回路不自交 则我们称该回路为合法的简单回路. 现在有 Q 个询问,每次询问有多少条合法的简单回路经过了 (x,y)

沈阳集训day5

问题 A: 李时珍的皮肤衣 题目描述 LSZ很皮!LSZ的皮肤衣更皮! LSZ有很多件神奇的皮肤衣,而且LSZ总是喜欢一次穿上多件皮肤衣(一件套一件,而且一直穿好多天),这些皮肤衣有透明或不透明两种状态,当不透明的皮肤衣吸收了一天的阳光直射后,就会变成透明的皮肤衣,透明的皮肤衣能使阳光照射到里层皮肤衣,而透明的皮肤衣再吸收阳光,会在第二天会变成不透明的皮肤衣,不透明的皮肤衣会阻止阳光照射到里层皮肤衣. LSZ从某天起(该天算作第1天)穿上N件皮肤衣(刚开始所有皮肤衣都是不透明的),问你最少要经过

【2019寒假集训DAY2】图论

Dijkstra 条件:无负权:时间:O(n*n) 详解+模板: https://www.cnblogs.com/jason2003/p/7222182.html (模板)P1821 [USACO07FEB]银牛派对Silver Cow Party:https://www.luogu.org/recordnew/show/12339877 void dj(){ for(int i=1;i<=m;i++) if(i!=k)dis[i]=M; for(int i=1;i<=m;i++){ int