A:
题目描述:
Today, Rikka is going to learn how to use BIT to solve some simple data structure tasks. While studying, She finds there is a magic expression x&(−x)x \& (-x)x&(−x) in the template of BIT. After searching for some literature, Rikka realizes it is the implementation of the function lowbit(x)\text{lowbit(x)}lowbit(x).
lowbit(x)\text{lowbit}(x)lowbit(x) is defined on all positive integers. Let a1...am be the binary representation of x while a1 is the least significant digit, k be the smallest index which satisfies ak = 1. The value of lowbit(x)\text{lowbit}(x)lowbit(x) is equal to 2k-1.
After getting some interesting properties of lowbit(x)\text{lowbit}(x)lowbit(x), Rikka sets a simple data structure task for you:
At first, Rikka defines an operator f(x), it takes a non-negative integer x. If x is equal to 0, it will return 0. Otherwise it will return x−lowbit(x)x-\text{lowbit}(x)x−lowbit(x) or x+lowbit(x)x+\text{lowbit}(x)x+lowbit(x), each with the probability of 12\frac{1}{2}21.
Then, Rikka shows a positive integer array A of length n, and she makes m operations on it.
There are two types of operations:
1. 1 L R, for each index i ∈ [L,R], change Ai to f(Ai).
2. 2 L R, query for the expectation value of ∑i=LRAi\sum_{i=L}^R A_i∑i=LRAi. (You may assume that each time Rikka calls f, the random variable used by f is independent with others.)
输入描述:
The first line contains a single integer t(1 ≤ t ≤ 3), the number of the testcases.
The first line of each testcase contains two integers n,m(1 ≤ n,m ≤ 105). The second line contains n integers Ai(1 ≤ Ai ≤ 108).
And then m lines follow, each line contains three integers t,L,R(t ∈ {1,2}, 1 ≤ L ≤ R ≤ n).
输出描述:
For each query, let w be the expectation value of the interval sum, you need to output (w×2nm)mod 998244353(w \times 2^{nm}) \mod 998244353(w×2nm)mod998244353.
It is easy to find that w x 2nm must be an integer.
示例:
输入:
1
3 6
1 2 3
1 3 3
2 1 3
1 3 3
2 1 3
1 1 3
2 1 3
输出:
1572864
1572864
1572864
题意:
给出一个大小为n的数组,对它进行以下两种操作:
操作1:给出l,r两个值,将[l,r]区间内每一个值x等概率得替换成x-bit(x)和x+bit(x).
操作2:给出L,R两值,求出该区间的期望值
题解:
对于操作一,我们很容易发现x替换后的f(x)的数学期望=0.5(x-bit(x))+0.5(x+bit(x))=x
则进行操作一时,可以在期望的角度对其不进行操作
对于操作二,求出区间和再乘以2的mn次方便可以求出答案
代码:
#include <bits/stdc++.h>
using namespace std;
//typedef long long ll; // -9223372036854775807ll - 1 ~ 9223372036854775807ll
#define int long long
#define INF 0X7FFFFFFF
#define MAXN 1000005
#define nullptr 0
#define debug(x) cout<<#x<<" : "<<x<<endl
#define Enter(i,n) (i==n) ? cout<<endl : cout<<" "
#define loop(i,x,n) for( int i = x ; i <= n ; ++i )
#define loop_(i,x,n) for( int i = x ; i >= n ; --i )
#define input(x) scanf("%lld",&x)
#define output(x) printf("%lld",x)
#define new_line printf("\n")
#define blank printf(" ")
const int MAX=0x3f3f3f3f3f3f3f3f;
const int mod=1e9+7;
const int Max=998244353;
const double eps=1e-8;
//代码预处理区域---------------------------------------------------------------------------------
int min(int x,int y){ return ( x & ( ( x-y ) >> 63 ) ) | ( y & ( ~ ( x-y ) >> 63 ) ) ; }
int max(int x,int y){ return ( y & ( ( x-y ) >> 63 ) ) | ( x & ( ~ ( x-y ) >> 63 ) ) ; }
int QuickPow( int x , int pow )
{
int res = 1 ;
x %= Max ;
// x %= mod ;
while( pow ){
if( pow & 1 ) res = ( res * x ) % Max ;
// if( pow & 1 ) res = ( res * x ) % mod ;
// if( pow & 1 ) res = res * x ;
x = ( x * x ) % Max ;
// x = ( x * x ) % mod ;
// x = x*x ;
pow >>= 1 ;
}
return res % Max ;
// return res ;
// return res % mod ;
}
int gcd( int a , int b )
{
if(!b) return a ;
return gcd( b , a%b ) ;
}
// 解决方案代码区--------------------------------------------------
const int N = 1e5+7 ;
const int M = 2e6+7 ;
int lowbit( int x )
{
return x & (-x) ;
}
int a[N] ;
int sum[N] ;
void solve()
{
int n , m ;
cin >> n >> m ;
int x ;
for( int i = 1 ; i <= n ; i ++ ){
cin >> x ;
a[i] = x ;
sum[i] = sum[i-1]+a[i] ;
}
int p , l , r ;
for( int i = 1 ; i <= m ; i ++ ){
cin >> p >> l >> r ;
if( p == 2 ){
int ans = sum[r] - sum[l-1] ;
cout << ans%Max*QuickPow( 2 , n*m )%Max << endl ;
}
}
return ;
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr),cout.tie(nullptr);
int _ = 1 ;
// input( _ ) ;
cin >> _ ;
// init() ;
while( _-- ){
// srand( (int)time(0) ) ;
solve() ;
}
return 0;
}
B:
题目描述:
Sometimes you may want to write a sentence into your nickname like "lubenwei niubi". But how to change it into a single word? Connect them one by one like "lubenweiniubi" looks stupid.
To generate a better nickname, Rikka designs a non-trivial algorithm to merge a string sequence s1...sn into a single string. The algorithm starts with s=s1 and merges s2...sn into s one by one. The result of merging t into s is the shortest string r which satisfies s is a prefix of r and t is a subsequence of r.(If there are still multiple candidates, take the lexicographic order smallest one.)
String s is a prefix of r if and only if |s| ≤ |r| and for all index i ∈ [1, |s|], si = ri.
String s is a subsequence of r if and only if there is an index sequence a1...a∣s∣(1≤a1<a2<...<a∣s∣≤∣r∣)a_1...a_{|s|}( 1 \leq a_1 < a_2 < ... < a_{|s|} \leq |r|)a1...a∣s∣(1≤a1<a2<...<a∣s∣≤∣r∣) which satisfies si=rais_i = r_{a_i}si=rai.
For example, if we want to generate a nickname from "lubenwei niubi", we will merge "niubi" into "lubenwei", and the result is "lubenweiubi".
Now, given a sentence s1...sn with n words, Rikka wants you to calculate the resulting nickname generated by this algorithm.
输入描述:
The first line contains a single number t(1 ≤ t ≤ 3), the number of testcases.
For each testcase, the first line contains one single integer n(1 ≤ n ≤ 106).
Then n lines follow, each line contains a lowercase string si(1≤∣si∣≤106,∑i=1n∣si∣≤106)s_i(1 \leq |s_i| \leq 10^6, \sum_{i=1}^n |s_i| \leq 10^6)si(1≤∣si∣≤106,∑i=1n∣si∣≤106).
输出描述:
For each testcase, output a single line with a single string, the result nickname.
示例:
输入:
2
2
lubenwei
niubi
3
aa
ab
abb
输出:
lubenweiubi
aabb
题意:
对于每一组数据,首先给出一个数字n来描述所需合并的字符串。首先输入的字符串会不变得作为绰号的开头(且称作主串),接下来每一行的字符串会从主串的第一个字母开始扫描,如果有相同的字母则该字母不接着录入字串,主串指针不回溯。最后输出这个主串
题解:
首先记录主串(第一个字符串)的每一个字符数目以及位置,在接下来的字串中,对于每一个子串:记录每一个字符的个数a[x]并初始化为0,主串上的指针重置为0,对于子串上的每一个字符,主串指针不断递增去去找是否有元素与之对应,如果有那么a[x]++,出现未有的情况则直接把后续字符全部录入,同时完善主串的字符记录。
通过代码:
//floor();向下取整
//ceil();向上取整
//rand();随机数
#include <bits/stdc++.h>
using namespace std;
//typedef long long ll; // -9223372036854775807ll - 1 ~ 9223372036854775807ll
#define int long long
#define INF 0X7FFFFFFF
#define MAXN 1000005
#define nullptr 0
#define debug(x) cout<<#x<<" : "<<x<<endl
#define Enter(i,n) (i==n) ? cout<<endl : cout<<" "
#define loop(i,x,n) for( int i = x ; i <= n ; ++i )
#define loop_(i,x,n) for( int i = x ; i >= n ; --i )
#define input(x) scanf("%lld",&x)
#define output(x) printf("%lld",x)
#define new_line printf("\n")
#define blank printf(" ")
const int MAX=0x3f3f3f3f3f3f3f3f;
const int mod=1e9+7;
const int Max=998244353;
const double eps=1e-8;
//代码预处理区域---------------------------------------------------------------------------------
int min(int x,int y){ return ( x & ( ( x-y ) >> 63 ) ) | ( y & ( ~ ( x-y ) >> 63 ) ) ; }
int max(int x,int y){ return ( y & ( ( x-y ) >> 63 ) ) | ( x & ( ~ ( x-y ) >> 63 ) ) ; }
int QuickPow( int x , int pow )
{
int res = 1 ;
// x %= Max ;
x %= mod ;
while( pow ){
// if( pow & 1 ) res = ( res * x ) % Max ;
if( pow & 1 ) res = ( res * x ) % mod ;
// if( pow & 1 ) res = res * x ;
// x = ( x * x ) % Max ;
x = ( x * x ) % mod ;
// x = x*x ;
pow >>= 1 ;
}
// return res % Max ;
// return res ;
return res % mod ;
}
int gcd( int a , int b )
{
if(!b) return a ;
return gcd( b , a%b ) ;
}
// 解决方案代码区--------------------------------------------------
const int N = 1e5+7 ;
const int M = 2e6+7 ;
vector< int > pos[30] ;
int a[30] ;
void solve()
{
for( int i = 0 ; i < 26 ; i ++ ) pos[i].clear() ;
int n ;
cin >> n ;
string s ;
cin >> s ;
for( int i = 0 ; i < s.size() ; i ++ ){
pos[ s[i]-'a' ].push_back( i ) ;
}
string p ;
for( int i = 2 ; i <= n ; i ++ ){
memset( a , 0 , sizeof a ) ;
cin >> p ;
int t = -1 ;
for( int j = 0 ; j < p.size() ; j ++ ){
int x = p[j]-'a' ;
if( pos[x].size() > a[x] ){
if( pos[x][ a[x] ] > t ){
t = pos[x][ a[x] ] ;
a[x]++ ;
}
else {
int temp = a[x] ;
while( pos[x][ temp ] < t && temp < pos[x].size() ){
temp ++ ;
}
if( temp < pos[x].size() ){
t = pos[ x ][temp] ;
a[x] = temp+1 ;
}
else {
int len = s.size() ;
for( int k = j ; k < p.size() ; k ++ ){
pos[ p[k]-'a' ].push_back( len++ ) ;
s += p[k] ;
}
break ;
}
}
}
else{
int len = s.size() ;
for( int k = j ; k < p.size() ; k ++ ){
pos[ p[k]-'a' ].push_back( len++ ) ;
s += p[k] ;
}
break ;
}
}
}
cout << s << endl ;
return ;
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr),cout.tie(nullptr);
int _ = 1 ;
// input( _ ) ;
cin >> _ ;
// init() ;
while( _-- ){
// srand( (int)time(0) ) ;
solve() ;
}
return 0;
}