文章目录

传送门

然而这场div2div2div2没有什么难度比较大的题

A题

传送门

题意简述:三个人分别至少选x,y,zx,y,zx,y,z件物品,有三种物品数量分别为a,b,ca,b,ca,b,c,其中第一个人只能选第一种,第二个人不能选第三种,第三个人随意问能否满足三个人需求。


思路:

直接模拟即可。

代码:

#include<bits/stdc++.h>
#define ri register int
#define fi first
#define se second
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int N=1e5+5,mod=1e9+7;
inline int add(const int&a,const int&b){return a+b>=mod?a+b-mod:a+b;}
inline int dec(const int&a,const int&b){return a>=b?a-b:a-b+mod;}
inline int mul(const int&a,const int&b){return (ll)a*b%mod;}
inline int read(){
	int ans=0,w=1;
	char ch=getchar();
	while(!isdigit(ch)){if(ch=='-')w=-1;ch=getchar();}
	while(isdigit(ch))ans=(ans<<3)+(ans<<1)+(ch^48),ch=getchar();
	return ans*w;
}
int x,y,z,a,b,c;
int main(){
	x=read(),y=read(),z=read(),a=read(),b=read(),c=read();
	if(x>a)return puts("NO"),0;
	a-=x;
	a+=b;
	if(y>a)return puts("NO"),0;
	a-=y,a+=c;
	if(z>a)return puts("NO"),0;
	puts("YES");
	return 0;
}

B题

传送门

题意简述:

要求把nnn个数的数列分成kkk份,每份至少有mmm个数,问这kkk份的前mmm大数之和的和最大值是多少,并要求给出一种构造方案。


思路:

显然可以构造出一种方案满足所有组的前mmm大拼起来是整个数列的前k∗mk*mk∗m大,排序分组即可。

代码:

#include<bits/stdc++.h>
#define ri register int
#define fi first
#define se second
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int N=2e5+5,mod=1e9+7;
inline int add(const int&a,const int&b){return a+b>=mod?a+b-mod:a+b;}
inline int dec(const int&a,const int&b){return a>=b?a-b:a-b+mod;}
inline int mul(const int&a,const int&b){return (ll)a*b%mod;}
inline int read(){
	int ans=0,w=1;
	char ch=getchar();
	while(!isdigit(ch)){if(ch=='-')w=-1;ch=getchar();}
	while(isdigit(ch))ans=(ans<<3)+(ans<<1)+(ch^48),ch=getchar();
	return ans*w;
}
int n,m,k;
struct Node{int val,id;}a[N];
inline bool cmp1(const Node&a,const Node&b){return a.val>b.val;}
inline bool cmp2(const Node&a,const Node&b){return a.id<b.id;}
int main(){
	n=read(),m=read(),k=read();
	for(ri i=1;i<=n;++i)a[i].val=read(),a[i].id=i;
	sort(a+1,a+n+1,cmp1);
	ll ans=0;
	for(ri i=1;i<=k*m;++i)ans+=a[i].val;
	cout<<ans<<'\n';
	sort(a+1,a+k*m+1,cmp2);
	for(ri i=m;i<k*m;i+=m)cout<<a[i].id<<' ';
	return 0;
}

C题

传送门

题意简述:给出 两个数n,b,n≤1e18,b≤1e12n,b,n\le1e18,b\le1e12n,b,n≤1e18,b≤1e12,问n!n!n!在bbb进制下有多少个后缀000。


思路:

令b=a1k1a2k2...apkpb=a_1^{k_1}a_2^{k_2}...a_p^{k_p}b=a1k1​​a2k2​​...apkp​​

然后算算n!n!n!中分别有多少个a1,a2,...,apa_1,a_2,...,a_pa1​,a2​,...,ap​,算出来之后除以kpk_pkp​更新答案即可。

注意不要爆long long

代码:

#include<bits/stdc++.h>
#define ri register int
#define fi first
#define se second
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int N=2e5+5,mod=1e9+7;
inline int add(const int&a,const int&b){return a+b>=mod?a+b-mod:a+b;}
inline int dec(const int&a,const int&b){return a>=b?a-b:a-b+mod;}
inline int mul(const int&a,const int&b){return (ll)a*b%mod;}
inline ll read(){
	ll ans=0,w=1;
	char ch=getchar();
	while(!isdigit(ch)){if(ch=='-')w=-1;ch=getchar();}
	while(isdigit(ch))ans=(ans<<3)+(ans<<1)+(ch^48),ch=getchar();
	return ans*w;
}
ll n,b;
inline ll calc(ll n,ll x,ll tim){
	ll res=0,ret=0;
	for(ll mul=x;mul<=n;mul*=x){
		ret+=n/mul;
		res+=ret/tim,ret%=tim;
		if(mul>n/x)break;
	}
	return res;
}
inline ll solve(ll n,ll p){
	ll res=2e18,up=p;
	for(ri i=2;(ll)i*i<=up;++i){
		if(p!=p/i*i)continue;
		ll cnt=0;
		while(p==p/i*i)p/=i,++cnt;
		res=min(res,calc(n,i,cnt));
	}
	if(p^1)res=min(res,calc(n,p,1));
	return res;
}
int main(){
	n=read(),b=read();
	cout<<solve(n,b);
	return 0;
}

D题

传送门

题意简述:给出一个nnn个数的数列(n≤5000)(n\le5000)(n≤5000),称一段相同的数为一个连通块,你每次可以选择一个连通块把它整体变成另一个数,问把整个数列变成同一个数的最少次数。


思路:先把连通块压成一个数,然后区间dpdpdp转移一下即可。

代码:

#include<bits/stdc++.h>
#define ri register int
#define fi first
#define se second
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int N=5005,mod=1e9+7;
inline int add(const int&a,const int&b){return a+b>=mod?a+b-mod:a+b;}
inline int dec(const int&a,const int&b){return a>=b?a-b:a-b+mod;}
inline int mul(const int&a,const int&b){return (ll)a*b%mod;}
inline ll read(){
	ll ans=0,w=1;
	char ch=getchar();
	while(!isdigit(ch)){if(ch=='-')w=-1;ch=getchar();}
	while(isdigit(ch))ans=(ans<<3)+(ans<<1)+(ch^48),ch=getchar();
	return ans*w;
}
inline void update(int&a,const int&b){a=b<a?b:a;}
int n,c[N],tot=0,f[N][N];
int main(){
	n=read();
	for(ri i=1;i<=n;++i)c[i]=read();
	for(ri i=1;i<=n;++i)if(c[i]^c[tot])c[++tot]=c[i];
	n=tot;
	memset(f,0x3f,sizeof(f));
	for(ri i=1;i<=n;++i)f[i][i]=0;
	for(ri len=2;len<=n;++len){
		for(ri l=1,r=l+len-1;r<=n;++l,++r){
			if(c[l]==c[r])update(f[l][r],f[l+1][r-1]+1);
			update(f[l][r],1+f[l+1][r]);
			update(f[l][r],f[l][r-1]+1);
		}
	}
	cout<<f[1][n];
	return 0;
}

E题

传送门

题意简述:交互题。

现在有一个nnn个数的n≤1e6n\le1e6n≤1e6的打乱顺序的等差数列,保证ai≤1e9,公差&gt;0a_i\le1e9,公差&gt;0ai​≤1e9,公差>0,你可以问不超过606060次来找到这个数列的首项和公差。

你可以问的问题如下:

  • &gt; x&gt;\ x> x:询问数列是否存在一个数&gt;x&gt;x>x,存在返回111否则返回000。
  • ? x?\ x? x:询问数列第xxx个数的值(打乱后的第xxx个)。

思路:先问第一种问题303030次找到数列的最大值,然后随机出一些位置求它们跟最大值差值的gcdgcdgcd作为公差。

代码:

#include<bits/stdc++.h>
#define ri register int
#define fi first
#define se second
using namespace std;
typedef long long ll;
typedef pair<int,ll> pii;
const int N=4e5+5,mod=1e9+7;
inline int add(const int&a,const int&b){return a+b>=mod?a+b-mod:a+b;}
inline int dec(const int&a,const int&b){return a>=b?a-b:a-b+mod;}
inline int mul(const int&a,const int&b){return (ll)a*b%mod;}
inline int ksm(int a,int p){int ret=1;for(;p;p>>=1,a=mul(a,a))if(p&1)ret=mul(ret,a);return ret;}
inline int read(){
	int ans=0;
	char ch=getchar();
	while(!isdigit(ch))ch=getchar();
	while(isdigit(ch))ans=(ans<<3)+(ans<<1)+(ch^48),ch=getchar();
	return ans;
}
int n,mx,d,mn;
map<int,int>mp;
int main(){
	srand(time(NULL));
	n=read();
	int l=0,r=1e9,mx=1e9;
	int tim=0;
	while(l<=r){
		int mid=l+r>>1;
		cout<<"> "<<mid<<endl<<endl;
		if(read())l=mid+1;
		else r=mid-1,mx=mid;
	}
	int d=0;
	for(ri x,i=1;i<=min(29,n);++i){
		while(1){
			x=(ll)rand()*rand()%n+1;
			if(!mp[x]){mp[x]=1;break;}
		}
		cout<<"? "<<x<<endl<<endl;
		x=read();
		d=__gcd(d,mx-x);
	}
	cout<<"! "<<mx-(n-1)*d<<' '<<d<<endl<<endl;
	return 0;
}

F题

传送门

题意简述:现在有一个长度为nnn的数列n≤4e5n\le4e5n≤4e5,数列里的数最开始≤300\le300≤300,现在要求支持如下操作:

  1. 区间乘一个数v≤300v\le300v≤300
  2. 求区间数的乘积的欧拉函数值。

询问数≤2e5\le2e5≤2e5,答案对1e9+71e9+71e9+7取模。


思路:询问操作相当于问的是这个东西:Mull,r∗∏primei,primei is a factor of Mul[l,r]primei−1primeiMul_{l,r}*\prod_{prime_i,prime_i\ is\ a\ factor\ of\ Mul_{[l,r]}} \frac{prime_i-1}{prime_i}Mull,r​∗∏primei​,primei​ is a factor of Mul[l,r]​​primei​primei​−1​

前面的积可以用线段树维护,考虑到300300300以内的素数只有626262个,我们把它们的存在性用一个longlonglong longlonglong压起来再用线段树维护即可。

代码:

#include<bits/stdc++.h>
#define ri register int
#define fi first
#define se second
using namespace std;
typedef long long ll;
typedef pair<int,ll> pii;
const int N=4e5+5,mod=1e9+7;
inline int add(const int&a,const int&b){return a+b>=mod?a+b-mod:a+b;}
inline int dec(const int&a,const int&b){return a>=b?a-b:a-b+mod;}
inline int mul(const int&a,const int&b){return (ll)a*b%mod;}
inline int ksm(int a,int p){int ret=1;for(;p;p>>=1,a=mul(a,a))if(p&1)ret=mul(ret,a);return ret;}
inline int read(){
	int ans=0;
	char ch=getchar();
	while(!isdigit(ch))ch=getchar();
	while(isdigit(ch))ans=(ans<<3)+(ans<<1)+(ch^48),ch=getchar();
	return ans;
}
int pri[305],invp[305],n,q,tot=-1;
bool vis[305];
inline void init(){
	for(ri i=2;i<=300;++i){
		if(!vis[i])pri[++tot]=i,invp[tot]=ksm(i,mod-2);
		for(ri j=0;j<=tot&&i*pri[j]<=300;++j){
			vis[i*pri[j]]=1;
			if(i==i/pri[j]*pri[j])break;
		}
	}
}
inline ll solve(int val){
	ll ret=0;
	for(ri i=0;i<=tot;++i)if(val==val/pri[i]*pri[i])ret|=1ll<<i;
	return ret;
}
namespace SGT{
	#define lc (p<<1)
	#define rc (p<<1|1)
	#define mid (l+r>>1)
	int val[N<<2],lz1[N<<2],len[N<<2];
	ll exi[N<<2],lz2[N<<2];
	inline void pushup(int p){val[p]=mul(val[lc],val[rc]),exi[p]=exi[lc]|exi[rc];}
	inline void pushnow(int p,int v1,ll v2){val[p]=mul(val[p],ksm(v1,len[p])),exi[p]|=v2,lz1[p]=mul(lz1[p],v1),lz2[p]|=v2;}
	inline void pushdown(int p){if(lz1[p]==1&&!lz2[p])return;pushnow(lc,lz1[p],lz2[p]),pushnow(rc,lz1[p],lz2[p]),lz1[p]=1,lz2[p]=0;}
	inline void build(int p,int l,int r){
		lz1[p]=1,lz2[p]=0,len[p]=r-l+1;
		if(l==r){exi[p]=solve((val[p]=read()));return;}
		build(lc,l,mid),build(rc,mid+1,r),pushup(p);
	}
	inline void update(int p,int l,int r,int ql,int qr,int v1,ll v2){
		if(ql<=l&&r<=qr)return pushnow(p,v1,v2);
		pushdown(p);
		if(qr<=mid)update(lc,l,mid,ql,qr,v1,v2);
		else if(ql>mid)update(rc,mid+1,r,ql,qr,v1,v2);
		else update(lc,l,mid,ql,mid,v1,v2),update(rc,mid+1,r,mid+1,qr,v1,v2);
		pushup(p);
	}
	inline pii query(int p,int l,int r,int ql,int qr){
		if(ql<=l&&r<=qr)return pii(val[p],exi[p]);
		pushdown(p);
		if(qr<=mid)return query(lc,l,mid,ql,qr);
		if(ql>mid)return query(rc,mid+1,r,ql,qr);
		pii a=query(lc,l,mid,ql,mid),b=query(rc,mid+1,r,mid+1,qr);
		return pii(mul(a.fi,b.fi),a.se|b.se);
	}
}
inline int calc(int v1,ll v2){
	for(ri i=0;i<=tot;++i)if((v2>>i)&1)v1=mul(v1,mul(pri[i]-1,invp[i]));
	return v1;
}
int main(){
	init(),n=read(),q=read();
	SGT::build(1,1,n);
	char s[10];
	for(ri tt=q,l,r,x;tt;--tt){
		scanf("%s",s),l=read(),r=read();
		if(s[0]=='T'){
			pii tmp=SGT::query(1,1,n,l,r);
			cout<<calc(tmp.fi,tmp.se)<<'\n';
		}
		else x=read(),SGT::update(1,1,n,l,r,x,solve(x));
	}
	return 0;
}

最新文章

  1. cookie 跨域访问的解决方案
  2. make基础(转)
  3. java中常用的工具类(二)
  4. 【pyQuery分析实例】分析体育网冠军联盟比赛成绩
  5. 越狱后如何添加cydia源及cydia源大全
  6. wifi current SSID
  7. git ssh key for github
  8. sqlite 修改表名,合并数据库(文件)
  9. js实现方法的链式调用
  10. iOS开发之视差滚动视图
  11. Nginx反向代理、CORS、JSONP等跨域请求解决方法总结
  12. vue组件递归
  13. 安卓TV开发(概述) 智能电视之视觉设计和体验分析
  14. [原创]X-HDL 4.2安装与使用
  15. tomcat文件下目录介绍
  16. Android 开发 Activity里获取View的宽度和高度 转载
  17. Xposed 框架 hook 简介 原理 案例 MD
  18. oracle的start with connect by prior如何使用
  19. Python 装饰器使用指南
  20. 三篇文章了解 TiDB 技术内幕 - 说存储(转)

热门文章

  1. Altium Designer9.4局域网内冲突的问题
  2. linux 时间和时区设置
  3. zookeeper 集群部署
  4. mysql数据库支持 emoji表情
  5. java中封装类(一)
  6. git 提交丢失Warning, you are leaving 2 commits behind,
  7. VS2010 Chart控件(一)Chart控件在ASP.NET网站中的应用示例详解(C#语言)
  8. MFC笔记4
  9. MYSQL分组合并函数
  10. WMS专业术语&amp;系统功能操作培训