18 18 18号的模拟赛我今天才想起来写···
T1 prime
区间筛法,因为 r r r的因数不会超过 r \sqrt{r} r,所以就可以先将 m i n ( k , r ) min(k,\sqrt{r}) min(k,r)以内的质数用线性筛筛出来,然后枚举每个质数,用埃式筛将 [ l , r ] [l,r] [l,r]的倍数都筛掉,最后剩下的就是合法的
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<map>
#define maxn 10000001
#define LL long long
using namespace std;
LL l,r;
int cnt,pri[maxn],ans,k;
map<LL,int> mp;
bool vis[maxn];
inline void get_prime(int n){
vis[1]=1;
for(int i=2;i<=n;i++){
if(!vis[i]) pri[++cnt]=i;
for(int j=1;j<=cnt && i*pri[j]<=n;j++){
vis[i*pri[j]]=1;
if(i%pri[j]==0) break;
}
}
}
int main(){
freopen("prime.in","r",stdin);
freopen("prime.out","w",stdout);
scanf("%lld%lld%d",&l,&r,&k);
int mn=min(k,(int)sqrt(r));
get_prime(mn);
for(int i=1;i<=cnt;i++){
LL ll=max(2LL,l/pri[i]);
for(LL j=ll;j*pri[i]<=r;j++)
mp[j*pri[i]]=1;
}
for(LL i=l;i<=r;i++){
if((i<=mn&&!vis[i]) || (i>mn&&!mp[i])) ans^=i;
}
printf("%d\n",ans);
return 0;
}
T2 sequence
考试的时候看成子串怎么调也调不出来···
因为
k
k
k比较小,所以可以按
k
k
k来
d
p
dp
dp,新加一个数字以后,他可以与所有其他数字结尾的那些序列构成新的子序列,自己也可以构成一个子序列,所以设
f
[
i
]
f[i]
f[i]表示以
i
i
i结尾的子序列有多少个,写出式子就是:
f
[
i
]
=
∑
j
=
1
k
f
[
j
]
+
1
f[i]=\sum_{j=1}^kf[j]+1
f[i]=j=1∑kf[j]+1
这样可以处理出给定的
n
n
n,可以看出如果想让结果最大每次一定要填最前面的那个,所以后面
m
m
m个就有一个
k
k
k的循环节,暴力找出后,矩阵加速即可
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#define maxn 105
#define maxm 1000005
#define int long long
using namespace std;
int n,m,K,f[maxn],lst[maxn],b[maxm];
const int mod=1e9+7;
inline int rd(){
int x=0,f=1;char c=' ';
while(c<'0' || c>'9') f=c=='-'?-1:1,c=getchar();
while(c<='9' && c>='0') x=x*10+c-'0',c=getchar();
return x*f;
}
struct Mat{
int a[maxn][maxn];
Mat(){memset(a,0,sizeof a);}
Mat operator *(const Mat &x) const{
Mat ret;
for(int k=1;k<=K+1;k++)
for(int i=1;i<=K+1;i++)
for(int j=1;j<=K+1;j++)
(ret.a[i][j]+=a[i][k]*x.a[k][j]%mod)%=mod;
return ret;
}
void init(){
for(int i=1;i<=K+1;i++) a[i][i]=1; return;
}
}g,s;
inline Mat qpow(Mat x,int k){
Mat ret; ret.init();
while(k){
if(k&1) ret=ret*x;
x=x*x; k>>=1;
} return ret;
}
struct Node{
int pos,val;
bool operator <(const Node &x) const{
return pos<x.pos;
}
}pr[maxn];
signed main(){
freopen("sequence.in","r",stdin);
freopen("sequence.out","w",stdout);
n=rd(); m=rd(); K=rd(); int sum=0;
for(int i=1;i<=n;i++) b[i]=rd();
for(int i=1;i<=n;i++){
sum=((sum-f[b[i]])%mod+mod)%mod;
(f[b[i]]+=(sum+1)%mod)%=mod; (sum+=f[b[i]])%=mod;
pr[b[i]].pos=i;
}
for(int i=1;i<=K;i++) pr[i].val=i;
sort(pr+1,pr+K+1);
for(int i=1;i<=K;i++)
s.a[1][i]=f[i];
s.a[1][K+1]=1;
g.init();
for(int i=1;i<=K;i++){
Mat tmp; tmp.init();
for(int j=1;j<=K+1;j++) tmp.a[j][pr[i].val]=1;
g=g*tmp;
}
int cnt=m/K,cnt2=m%K;
s=s*qpow(g,cnt); sum=0;
for(int i=1;i<=K;i++) f[i]=s.a[1][i],(sum+=s.a[1][i])%=mod;
for(int i=1;i<=cnt2;i++){
int j=pr[i].val;
sum=((sum-f[j])%mod+mod)%mod;
(f[j]+=(sum+1)%mod)%=mod; (sum+=f[j])%=mod;
}
printf("%lld\n",sum);
return 0;
}
/*
5 6 3
3 1 2 1 2
*/
T3 omeed
一道期望题···推式子很好推但是有个地方没注意结果暴力都没打出来。(就是那个地方是 c [ i − 1 ] + 1 c[i-1]+1 c[i−1]+1 不是 c [ i ] c[i] c[i]
推出式子以后用线段树维护系数,这个好像在 j z jz jz讲过当时没做这个题就没听血亏
大概就是 c R c_{R} cR和 C o m b o o [ L , R ] Comboo[L,R] Comboo[L,R]都可以表示成 k ∗ c L − 1 + b k*c_{L-1}+b k∗cL−1+b的形式,然后维护两组系数, k 1 k1 k1和 b 1 b1 b1是 c R c_R cR的, k 2 k2 k2和 b 2 b2 b2是 C o m b o o Comboo Comboo的,最后答案就是 b 2 ∗ B + s u m p ∗ A b2*B+sump*A b2∗B+sump∗A
代码不太会打就参考了别人的博客打的 q w q qwq qwq
#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cmath>
#define N 500005
#define ls cur<<1
#define rs cur<<1|1
#define LL long long
#define int LL
using namespace std;
int n,m,A,B,t,p[N],id;
const int mod=998244353;
inline int rd(){
int x=0,f=1;char c=' ';
while(c<'0' || c>'9') f=c=='-'?-1:1,c=getchar();
while(c<='9' && c>='0') x=x*10+c-'0',c=getchar();
return x*f;
}
inline LL qpow(LL x,int k){
LL ret=1;
while(k){
if(k&1) (ret*=x)%=mod;
(x*=x)%=mod; k>>=1;
} return ret;
}
inline LL inv(LL x){return qpow(x,mod-2);}
struct Node{
int sump,k1,b1,k2,b2;
Node(){sump=k1=b1=k2=b2=0;}
Node operator +(const Node &x) const{
Node ret;
ret.sump=(sump+x.sump)%mod;
ret.k1=x.k1*k1%mod;
ret.b1=(x.k1*b1%mod+x.b1)%mod;
ret.k2=(x.k2*k1%mod+k2)%mod;
ret.b2=(x.k2*b1%mod+x.b2+b2)%mod;
return ret;
}
}node[N<<1];
inline void pushup(int cur){
node[cur]=node[ls]+node[rs];
}
void build(int cur,int L,int R){
if(L==R){
node[cur].k1=(t+p[L]-p[L]*t%mod+mod)%mod;
node[cur].b1=p[L];
node[cur].k2=p[L];
node[cur].b2=p[L];
node[cur].sump=p[L]; return;
}
int mid=(L+R)>>1;
build(ls,L,mid); build(rs,mid+1,R);
pushup(cur);
}
void update(int cur,int L,int R,int l,int r,int c){
if(L==R){
node[cur].k1=(t+c-c*t%mod+mod)%mod;
node[cur].b1=node[cur].k2=node[cur].b2=node[cur].sump=c;
return;
}
int mid=(L+R)>>1;
if(l<=mid) update(ls,L,mid,l,r,c);
else update(rs,mid+1,R,l,r,c); pushup(cur);
}
Node query(int cur,int L,int R,int l,int r){
if(l<=L && R<=r) return node[cur];
int mid=(L+R)>>1;
if(r<=mid) return query(ls,L,mid,l,r);
if(l>mid) return query(rs,mid+1,R,l,r);
return query(ls,L,mid,l,r)+query(rs,mid+1,R,l,r);
}
signed main(){
id=rd(); n=rd(); m=rd(); t=rd(); int x=rd(); t=inv(x)*t%mod;
A=rd(); B=rd();
for(int i=1;i<=n;i++){
int a=rd()%mod,b=rd();
p[i]=a*inv(b)%mod;
}
build(1,1,n);
while(m--){
if(rd()==0){
int x=rd(),a=rd(),b=rd(),c=inv(b)*a%mod;
p[x]=c; update(1,1,n,x,x,c);
}
else{
int ll=rd(),rr=rd();
Node ans=query(1,1,n,ll,rr);
printf("%d\n",(ans.sump*A%mod+ans.b2*B%mod)%mod);
}
}
return 0;
}