# 101 Hack 44

### A. Picking Numbers(水题)

https://www.hackerrank.com/contests/101hack44/challenges/picking-numbers

#### 题目分析：

#include <bits/stdc++.h>
using namespace std;

#define RE(x) freopen(x,"r",stdin)
#define WR(x) freopen(x,"w",stdout)
#define ms(x,y) memset(x,y,sizeof(x))
#define pb push_back
#define mp make_pair
#define INF 0x3f3f3f3f
#define eps 1e-8

typedef long long ll;
typedef vector<int> vi;
typedef pair<int,int> pi;
typedef vector<ll> vl;

const int M = 1e9 + 7;
const double PI = acos(-1.0);

const int MAXN = 1e5 + 5;
const int MAXM = 1e6 + 5;

int main() {
//RE("in.txt");WR("out.txt");
int n;
int a[105];
cin>>n;
for (int i = 0; i < n; i++)
cin>>a[i];
sort(a,a+n);
int ans=0;
for(int i=0;i<n;i++) {
int temp=1;
for(int j=i+1;j<n;j++) {
if(a[j]-a[i]<=1)
temp++;
}
ans=max(ans,temp);
}
cout<<ans<<endl;
}

### B.Alice and Bob’s Silly Game(素数统计)

https://www.hackerrank.com/contests/101hack44/challenges/alice-and-bobs-silly-game

#### 题目分析：

#include <bits/stdc++.h>
using namespace std;

#define RE(x) freopen(x,"r",stdin)
#define WR(x) freopen(x,"w",stdout)
#define ms(x,y) memset(x,y,sizeof(x))
#define pb push_back
#define mp make_pair
#define INF 0x3f3f3f3f
#define eps 1e-8

typedef long long ll;
typedef vector<int> vi;
typedef pair<int,int> pi;
typedef vector<ll> vl;

const int M = 1e9 + 7;
const double PI = acos(-1.0);

const int MAXN = 1e5 + 5;
const int MAXM = 1e6 + 6;

ll f[340000],g[340000],n;
void init(){
ll i,j,m;
for(m=1;m*m<=n;++m)f[m]=n/m-1;
for(i=1;i<=m;++i)g[i]=i-1;
for(i=2;i<=m;++i){
if(g[i]==g[i-1])continue;
for(j=1;j<=min(m-1,n/i/i);++j){
if(i*j<m)f[j]-=f[i*j]-g[i-1];
else f[j]-=g[n/i/j]-g[i-1];
}
for(j=m;j>=i*i;--j)g[j]-=g[j/i]-g[i-1];
}
}
int main(){
int t;
cin>>t;
while(t--){
cin>>n;
init();
if(f[1]&1)
cout<<"Alice"<<endl;
else
{
cout<<"Bob"<<endl;
}
}
return 0;
}

### C.Expected Tree Leaves(概率与期望)

https://www.hackerrank.com/contests/101hack44/challenges/expected-tree-leaves

#### 题目分析：

E=i=1nPi

Pi=i1iii+1...n2n1=i1n1

#include <bits/stdc++.h>
using namespace std;

#define RE(x) freopen(x,"r",stdin)
#define WR(x) freopen(x,"w",stdout)
#define ms(x,y) memset(x,y,sizeof(x))
#define pb push_back
#define mp make_pair
#define INF 0x3f3f3f3f
#define eps 1e-8

typedef long long ll;
typedef vector<int> vi;
typedef pair<int,int> pi;
typedef vector<ll> vl;

const int M = 1e9 + 7;
const double PI = acos(-1.0);

const int MAXN = 1e5 + 5;
const int MAXM = 1e6 + 6;

int main() {
//RE("in.txt");WR("out.txt");
ll f[MAXN];
f[1]=1;
for(int i=2;i<=100000;i++) {
f[i]=(f[i-1]*i)%M;
}
ll n;
cin>>n;
ll x=n*(1e9+8)/2;
x=x%M;
cout<<x*f[n]%M<<endl;
}

### D.Palindromic Subsets(线段树+组合数计算)

https://www.hackerrank.com/contests/101hack44/challenges/palindromic-subsets

#### 题目大意：

* 1 i j t:对s的[i,j]子串的字母循环右移t个（下标从0开始）
* 2 i j:问s的[i,j]子串中，有多少个子串可以重排成回文串（这里没注意，导致本题一直没做出来，蠢死了），下标不同认为是不同的子串
n,q范围均为1e5.

#### 题目分析：

even[0]=8(0个a有1个，2个a有C(4,2)=6个，4个a有1个）

odd[0]=8(1个a有C(4,1)=4个，3个a有C(4,3)=4个)

i=025even[0]...even[i1]odd[i]even[i+1]...even[25]

i=025pre[i]odd[i]suf[i]

#include <bits/stdc++.h>
using namespace std;

#define RE(x) freopen(x,"r",stdin)
#define WR(x) freopen(x,"w",stdout)
#define ms(x,y) memset(x,y,sizeof(x))
#define pb push_back
#define mp make_pair
#define INF 0x3f3f3f3f
#define eps 1e-8

#define LEFT idx<<1,begin,mid
#define RIGHT idx<<1|1,mid+1,end

typedef long long ll;
typedef vector<int> vi;
typedef pair<int,int> pi;
typedef vector<ll> vl;

const int M = 1e9 + 7;
const double PI = acos(-1.0);

const int MAXN = 1e5 + 5;
const int MAXM = 1e6 + 6;

int n,q;
char s[123456];
struct node {
int lazy;
int cnt[30];
}segtree[1<<18],id;

ll qmod(ll a,ll b,ll c) {
ll ans=1;
a=a%c;
while(b>0) {
if(b&1)
ans=(ans*a)%c;
b=b/2;
a=(a*a)%c;
}
return ans;
}

node merge(node a,node b) {
node c;
c.lazy=0;
for(int i=0;i<26;i++) {
c.cnt[i]=a.cnt[(i+a.lazy)%26]+b.cnt[(i+b.lazy)%26];
}
return c;
}

void apply(int a,int b) {
segtree[a].lazy+=b;
}

void down(int x) {
if(segtree[x].lazy) {
apply(x*2, segtree[x].lazy);
apply(x*2+1, segtree[x].lazy);
node c;
c.lazy=0;
for(int i=0;i<26;i++)
c.cnt[i]=segtree[x].cnt[(i+segtree[x].lazy)%26];
segtree[x]=c;
}
}

void build(int idx,int begin,int end) {
if(begin==end)
segtree[idx].cnt[s[begin-1]-'a']++;
else {
int mid=(begin+end)/2;
build(LEFT);
build(RIGHT);
segtree[idx]=merge(segtree[idx*2],segtree[idx*2+1]);
}
}

void update(int idx,int begin,int end,int l,int r,int v) {
if(r<begin || end<l)
return;
if(l<=begin && end<=r)
apply(idx,v);
else {
down(idx);
int mid=(begin+end)/2;
update(LEFT,l,r,v);
update(RIGHT,l,r,v);
segtree[idx]=merge(segtree[idx*2],segtree[idx*2+1]);
}
}

node query(int idx,int begin,int end,int l,int r) {
if(r<begin || end<l)
return id;
if(l<=begin && end<=r)
return segtree[idx];
else {
down(idx);
int mid=(begin+end)/2;
node a=query(LEFT,l,r);
node b=query(RIGHT,l,r);
return merge(a,b);
}
}

void shift(int i,int j,int t) {
update(1,1,n,i+1,j+1,(26-(t%26))%26);
}

ll solve(int x,int y) {
ll pre[27],suf[27],even[27],odd[27];
for(int i=0;i<27;i++) {
pre[i]=0;suf[i]=0;even[i]=0;odd[i]=0;
}
node d=query(1,1,n,x+1,y+1);//得到结果节点
for(int i=0;i<26;i++) {
int c=d.cnt[i];
if(c==0) {
even[i]=1;
odd[i]=0;
}
else {
even[i]=odd[i]=qmod(2,c-1,M);//直接用1<<(c-1)肯定会爆ll
}
}
pre[0]=1;suf[26]=1;
for(int i=1;i<=26;i++)
pre[i]=(pre[i-1]*even[i-1])%M;
for(int i=25;i>=0;i--)
suf[i]=(suf[i+1]*even[i])%M;
ll ans=suf[0];//不考虑奇数个字母的出现，答案为(even[0]*...*even[25])%M

for(int i=0;i<26;i++) {
ll temp=(pre[i]*odd[i])%M;
temp=(temp*suf[i+1])%M;
ans=(ans+temp)%M;
}
return ans-1;

}

int main() {
RE("in.txt");WR("out.txt");
cin>>n>>q;
cin>>s;
// cout<<n<<" "<<q<<endl;
// cout<<s<<endl;
build(1,1,n);
while(q--) {
int op,x,y,t;
cin>>op;
if(op==1) {
cin>>x>>y>>t;
shift(x,y,t);
}
else {
cin>>x>>y;
cout<<solve(x,y)<<endl;
}
}
}