1001——Picking Numbers
Picking Numbers题目
水题,差小于1的两个数的个数最大
#include <cmath>
#include <cstdio>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
int arr[110];
int main() {
int n,data;
scanf("%d",&n);
for(int i = 0;i<n;i++) {
scanf("%d",&data);
arr[data]++;
}
int ans = arr[0];
for(int i = 0;i<100;i++) ans =max(ans,arr[i]+arr[i+1]);
printf("%d\n",ans);
return 0;
}
1002——Alice and Bob’s Silly Game
Alice and Bob’s Silly Game题目
博弈的问题,给你n个数,每次可以选择一个素数,将素数和素数的倍数的数删除,如果不能删除则为输。我们会发现这个题的本质就是给你小于的n的素数,每次可以从中选择一个素数删除,直到不能删除为止。那么如果素数的个数为奇数则Alice赢,否则Bob赢。
#include <bits/stdc++.h>
using namespace std;
const int maxn=1e5+100;
int vis[maxn];
void Get() {
memset(vis,1,sizeof(vis));
vis[0] = vis[1] = 0;
for(int i = 2;i<maxn;i++) {
if(vis[i]) {
for(int j = i+i;j<maxn;j+=i) vis[j] = 0;
}
}
for(int i = 0;i<maxn;i++) vis[i] = vis[i]+vis[i-1];
}
int main() {
Get();
int n,T;
scanf("%d",&T);
while(T--) {
scanf("%d",&n);
if(vis[n]&1) printf("Alice\n");
else printf("Bob\n");
}
return 0;
}
1003——Expected Tree Leaves
Expected Tree Leaves题目
将节点从小到大放置,每次选择一个小的节点放在他的后面,问形成的树的叶子节点的个数的期望
我们计算第i个节点为叶子节点的期望,那么我们假设
i
i
i为叶子节点,那么第
i
+
1
i+1
i+1的节点的概率为
i
−
1
i
\frac{i-1}{i}
ii−1,第
i
+
2
i+2
i+2的节点的概率为
i
i
+
1
\frac{i}{i+1}
i+1i,那么第
i
i
i个节点为叶子的概率为
P
i
=
i
−
1
i
×
i
i
+
1
+
⋯
+
n
−
2
n
−
1
=
i
−
1
n
−
1
P_i = \frac{i-1}{i}\times \frac{i}{i+1}+\cdots+\frac{n-2}{n-1} = \frac{i-1}{n-1}
Pi=ii−1×i+1i+⋯+n−1n−2=n−1i−1,所以
E
=
∑
i
=
2
n
=
1
n
−
1
+
2
n
−
1
+
⋯
+
n
−
1
n
−
1
=
∑
i
=
1
n
−
1
n
−
1
=
n
×
(
n
−
1
)
2
n
−
1
=
n
2
E = \sum\limits_{i=2}^n=\frac{1}{n-1}+\frac{2}{n-1} + \cdots+\frac{n-1}{n-1} = \frac{\sum\limits_{i=1}^{n-1}}{n-1} = \frac{\frac{n\times(n-1)}{2}}{n-1} = \frac{n}{2}
E=i=2∑n=n−11+n−12+⋯+n−1n−1=n−1i=1∑n−1=n−12n×(n−1)=2n,所以
a
n
s
=
n
2
×
n
!
ans = \frac{n}{2}\times n!
ans=2n×n!
#include <bits/stdc++.h>
using namespace std;
const int mod = 1e9+7;
typedef long long LL;
int main() {
int n;
LL ans;
scanf("%d",&n);
ans = n;
for(int i = 3;i<=n;i++) ans = (ans*i)%mod;
printf("%lld\n",ans);
return 0;
}
1004——Palindromic Subsets
Palindromic Subsets 题目
给你一个字符串,有两种操作,一种是对于区间[L,R]中的字符,向后移动T个字符既
C
i
=
(
C
i
+
26
)
%
26
C_i = (C_i+26)\%26
Ci=(Ci+26)%26,第二种操作是询问区间[L,R]可以组成多少个回文串
对于一个区间,我们对于第一种操作,可以通过线段树实现,那么对于第二种操作,我们假设已经知道区间[L,R]种每一个字符的个数
N
u
m
i
0
≤
i
≤
25
Num_i\ 0\le i \le 25
Numi 0≤i≤25,对于一个字母
i
i
i可以组成多少个回文串呢?显然是
2
N
u
m
i
2^{Num_i}
2Numi个,其中长度为奇数和偶数的个数相同均为
2
N
u
m
i
−
1
2^{Num_i-1}
2Numi−1种。显然最后组成的回文串分为两种,一种是长度为奇数的,一种是长度为偶数的。对于长度为偶数的,答案就是多有字符组成长度为偶数的个数的乘积,奇数就是我们枚举长度为奇数的字符串,那么答案就是非枚举字符的偶数的乘积与枚举字符的奇数乘积。
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int maxn = 1e5+100;
const int mod = 1e9+7;
struct node {
int lazy;
int num[26];
void Clear() {
lazy = 0;
memset(num,0,sizeof(num));
}
}tr[maxn*5];
char str[maxn];
int Pow[maxn];
int suffix[30],prefix[30],odd[30],even[30];
int n,q;
node ans;
void pushup(int st) {
for(int i = 0;i<26;i++) tr[st].num[i] = tr[st<<1].num[i]+tr[st<<1|1].num[i];
}
void build(int L,int R,int st) {
tr[st].Clear();
if(L==R) {
tr[st].num[str[L-1] - 'a']++;
return ;
}
int mid = (L+R) >>1;
build(L,mid,st<<1);
build(mid+1,R,st<<1|1);
pushup(st);
}
node Rotate(node a,int b) {
node ans; ans.Clear();
ans.lazy = a.lazy;
for(int i = 0;i<26;i++) ans.num[(i+b)%26] = a.num[i];
return ans;
}
void pushdown(int L,int R,int st) {
if(L==R || tr[st].lazy == 0) return ;
tr[st<<1].lazy = (tr[st<<1].lazy+tr[st].lazy)%26;
tr[st<<1|1].lazy =(tr[st<<1|1].lazy+tr[st].lazy)%26;
tr[st<<1] = Rotate(tr[st<<1],tr[st].lazy);
tr[st<<1|1] = Rotate(tr[st<<1|1],tr[st].lazy);
tr[st].lazy = 0;
}
void Update(int L,int R,int st,int l,int r,int tm) {
if(l<=L && R<=r) {
tr[st].lazy = (tr[st].lazy+tm)%26;
tr[st] = Rotate(tr[st],tm);
return ;
}
pushdown(L,R,st);
int mid = (L+R) >>1;
if(l<=mid) Update(L,mid,st<<1,l,r,tm);
if(r> mid) Update(mid+1,R,st<<1|1,l,r,tm);
pushup(st);
}
void Query(int L,int R,int st,int l,int r) {
if(l<=L && R<=r) {
for(int i = 0;i<26;i++) ans.num[i] = ans.num[i]+tr[st].num[i];
return ;
}
pushdown(L,R,st);
int mid = (L+R)>>1;
if(l<=mid) Query(L,mid,st<<1,l,r);
if(r>mid) Query(mid+1,R,st<<1|1,l,r);
pushup(st);
}
int Count() {
int ant = 1;
for(int i = 0;i<26;i++) {
if(ans.num[i] ==0) {
odd[i] = 0;
even[i] = 1;
}
else {
odd[i] = Pow[ans.num[i]-1];
even[i] = Pow[ans.num[i]-1];
}
}
prefix[0] = even[0];
for(int i = 1;i<26;i++) prefix[i] = (prefix[i-1]*1LL*even[i])%mod;
suffix[25] = even[25];
for(int i = 24;i>=0;i--) suffix[i] = (suffix[i+1]*1LL*even[i])%mod;
ant = prefix[25];
for(int i = 0;i<26;i++) {
int cur = ((i == 0?1:prefix[i-1])*1LL*(i==25?1:suffix[i+1]))%mod;
cur = (cur*1LL*odd[i])%mod;
ant = (ant+cur)%mod;
}
return (ant-1+mod)%mod;
}
int main() {
scanf("%d %d",&n,&q);
int op,l,r,tm;
Pow[0] = 1;
for(int i = 1;i<maxn;i++) Pow[i] = (Pow[i-1]<<1)%mod;
scanf("%s",str);
build(1,n,1);
while(q--) {
scanf("%d %d %d",&op,&l,&r);
if(op == 1) scanf("%d",&tm);
l++,r++;
if(op == 1) {
Update(1,n,1,l,r,tm%26);
}
else {
ans.Clear();
Query(1,n,1,l,r);
printf("%d\n",Count());
}
}
return 0;
}