沈阳集训day2
Posted edsheeran
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了沈阳集训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); }
问题 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(" "); } }
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(" "); } }
问题 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; }
以上是关于沈阳集训day2的主要内容,如果未能解决你的问题,请参考以下文章