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的值即可。
数据范围
对于前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: 女神
题目描述
输入
输出
样例输入
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