2018.10.18模拟赛

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

考试的时候看成子串怎么调也调不出来···

原题是jzoj5836

因为 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=1kf[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[i1]+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 kcL1+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 b2B+sumpA

代码不太会打就参考了别人的博客打的 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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值