首页 > 其他分享 >CF1114

CF1114

时间:2024-11-22 16:31:17浏览次数:1  
标签:10 CF1114 tr times int id leqslant

A.Got Any Grapes?

CF原题链接

题目大意:

给出三种葡萄的数目\(x,y,z\),给出三个人要吃的数目\(a,b,c\),已知第一人只吃第一种葡萄,第二人只吃前两种葡萄,第三人三种葡萄都吃,问是否可以满足他们的要求。\((1\leqslant x,y,z,a,b,c\leqslant 10^{5})\)

解题思路:

直接模拟即可。从要求多的开始处理,最后剩下的给要求少的;这样若一个人存在无法满足要求的情况,那么一定无解。

小代码
#incIude <bits/stdc++.h>
#define int long long
using namespace std;
int x,y,z,a,b,c;

signed main()
{
	scanf("%lld%lld%lld",&x,&y,&z);
	scanf("%lld%lld%lld",&a,&b,&c);
	a-=x;
	if (a<0) {  printf("NO"); return 0;  }
	b-=y-a;
	if (b<0) {  printf("NO"); return 0;  }
	c-=z-b;
	if (c<0) {  printf("NO"); return 0;  }
	printf("YES");
	return 0;
}

B.Yet Another Array Partitioning Task

CF原题链接

题目大意:

我们定义一个序列的“美丽度”为序列前\(m\)大的数的和。给出长度为\(n\)的一个序列\(a_{i}\),要求将序列\(a\)分为\(k\)个连续子序列,使得每个连续子序列长度至少为\(m\),每个元素不重不漏,且所有子段“美丽度”的和最大。输出最大的“美丽度”之和与划分方案。\((1\leqslant n\leqslant 2\times 10^{5},m\geqslant 1,k\geqslant 2,m\times k\leqslant n,-10^{9}\leqslant a_{i}\leqslant 10^{9})\)

解题思路:

因为“原序列中前\(m\times k\)大的数”字太多了,所以下面用“天选之数”代替

显然,最大的美丽度之和就是"原序列中前\(m\times k\)大的数"之和。先求出最大美丽度和并统计哪些数是天选之数;划分子段时,记录目前子段有多少个天选之数,若当前子段已经有\(m\)个了,那么在当前位置划分一下即可。

挂分小技巧 但是,要注意除了要记录哪些数是天选之数,还要记录每个天选之数的个数;否则会出现以下情况:对于所有\(a_{i}=x\),部分\(a_{i}\)属于天选之数,部分\(a_{i}\)不属于天选之数,因为没记录天选之数的个数,所以对于部分不属于天选之数的\(a_{i}\)也用于划分子段了——但它其实并不能用。

再次注意到\(a_{i}\)的范围,再次用map搞桶数组。

坏代码
#incIude <bits/stdc++.h>
#define int long long
using namespace std;
const int N=2e5+5;
int n,m,k;
struct node{
	int x,d;
}a[N];

map <int,int> mp;
int l,sum;
int cnt=1,s[N];

bool cmp1(node x,node y) {  return x.x>y.x;  }
bool cmp2(node x,node y) {  return x.d<y.d;  }
signed main()
{
	scanf("%lld%lld%lld",&n,&m,&k);
	for (int i=1;i<=n;i++) 
	{
		scanf("%lld",&a[i].x);
		a[i].d=i;
	}
	
	sort(a+1,a+1+n,cmp1);
	for (int i=1;i<=m*k;i++) 
	{
		sum+=a[i].x;	
		mp[a[i].x]++;
	}
	sort(a+1,a+1+n,cmp2);
	
	int ct=0;
	for (int i=1;i<=n;i++)
	{
		if (mp[a[i].x]) {  ct++; mp[a[i].x]--;  }
		if (ct>=m) {  ct=0; s[++cnt]=i;  }
	}
	
	printf("%lld\n",sum);
	for (int i=2;i<=k;i++) printf("%lld ",s[i]);
	return 0;
}

C.Trailing Loves

CF原题链接

题目大意:

给出\(n\),求 \(n!\) 在\(b\)进制下末尾\(0\)的个数。\((1\leqslant n\leqslant 10^{18},2\leqslant b\leqslant 10^{12})\)

解题思路:

作为一个数论知识储备基本为0的蒟蒻 一道数论黄题足以让我欲哭无泪
什么?另一道题面相同的题是蓝题?

联想到短除法的过程,能够想到对于一个数\(n\),其在\(b\)进制下末尾0的个数\(p\)就是它能整除\(b\)的个数,即$$n=k^{\ p}\times w$$于是分别给\(n!,b\)分解分解质因子,形如$$b={p_{1}}^{a1} {p_{2}}^{a2}… {p_{3}}^{a3}, n!={p_{1}}^{e1} {p_{2}}^{e2}… {p_{3}}^{e3}$$那么最后的答案就是\(min\{\lfloor\frac{e_{i}}{a_{i}}\rfloor\}\)

但是考虑到给\(n!\)分解质因子不现实,发现只需要给\(b\)分解即可;因为\(n!=1\times 2\times…\times n\),所以每\(p\)个数中就有一个数的质因子含\(p\),于是乎\(e_{i}=\sum_{i=1}^{r}\lfloor \frac{n}{p^{i}} \rfloor,p^{r}\leqslant n< p^{r+1}\)

难绷的代码
#incIude <bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e6;
const int inf=0x3f3f3f3f3f3f3f3f;
int n,b;
struct node{
	int x,num;
}p[N];
int cnt;
int ans=inf;

signed main()
{
	scanf("%lld%lld",&n,&b);
	
	for (int i=2;i*i<=b;i++)//b的质因子 
	{
		if (b%i==0) 
		{
			p[++cnt].x=i;
			while (b%i==0) {  p[cnt].num++; b/=i;  }
		}
	}
	if (b>1) p[++cnt]={b,1};
	
	for (int i=1;i<=cnt;i++)
	{
		int r=1,e=0;
		while (n/r>=p[i].x)
		{
			r*=p[i].x;
			e+=n/r;
		}
		ans=min(ans,e/p[i].num);
	}
	
	printf("%lld",ans);
	return 0;
}

D.Food Fill

CF原题链接

题目大意:

给出长度为\(n\)的序列\(c_{i}\),定义区间\([l,r]\)合法当且仅当\(c_{l}=c_{l+1}=…=c_{r}\)。每次操作可以选择一个\(c_{i}\)并将\(c_{i}\)所在的合法区间修改为其他数,求使得\([1,n]\)为合法区间的最少操作次数。\((1\leqslant n,c_{i}\leqslant5000)\)

解题思路:

一眼区间\(dp\)。

设状态\(f_{i,j}\)表示使区间\([i,j]\)合法的最小代价。状态转移方程如

\[f_{i,j}=\begin{cases} f_{i+1,j-1}+1,c_{i}=c_{j}\\ min(f_{i+1,j},f_{i,j-1})+1,c_{i}\neq c_{j} \end{cases}\]

和木板涂色简直一样一样的

修代码
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N=5010;
int n;
int cnt,c[N];
int f[N][N];

signed main()
{
	scanf("%lld",&n);
	for (int i=1,x,pre=0;i<=n;i++)
	{
		scanf("%lld",&x);
		if (x!=pre) c[++cnt]=x;
		pre=x;
	}
	
	for (int len=2;len<=cnt;len++)
	{
		for (int i=1;i+len-1<=cnt;i++)
		{
			int j=i+len-1;
			if (c[i]==c[j]) f[i][j]=f[i+1][j-1]+1;
			else f[i][j]=min(f[i+1][j],f[i][j-1])+1;
		}
	}
	
	printf("%lld",f[1][cnt]);
	return 0;
}

E.Arithmetic Progession

CF原题链接

题目大意:

已知有一个长度为\(n\)的序列\(a_{i}\),保证它升序排序后是个等差数列。每次有两种询问:

  1. "? i" 询问\(a_{i}\)的值
  2. "> x" 询问序列中是否存在严格大于\(x\)的数

可以问不超过60个询问。

要求输出等差数列的首项与公差。\((2\leqslant n\leqslant 10^{6},0\leqslant a_{i}\leqslant 10^{9})\)

解题思路:

不会


F.Please,another Qeuries on Array?

CF原题链接

题目大意:

给出长度为\(n\)的序列\(a\),现在要完成\(q\)次操作,有以下两种操作形式:

  1. "MULTIPLY , l , r , x",对于\(i\in[l,r]\),使得\(a_{i}=a_{i}\times x\)
  2. "TOTIENT , l , r",输出 \(\varphi(\prod_{i=l}^{r}{a_{i}})\mod10^{9}+7\)

\((1\leqslant n\leqslant 4\times 10^{5},1\leqslant q\leqslant 2\times 10^{5},1\leqslant a_{i},x\leqslant 300)\)

解题思路:

区修区查,一眼线段树。问题在于怎样维护\(\varphi\)值。

首先,欧拉函数的计算方式为$$\varphi(n)=n\times \prod_{i=1}^{k}{\frac{p_{i}-1}{p_{i}}} $$其中\(p_{i}\)是\(n\)的质因子,\(k\)是\(n\)的质因子的个数。

所以,要求欧拉函数,就需要维护\(a_{i}\)的质因子。注意到\(a_{i}\)与\(x\)的范围不超过300,而300以内的质数有62个,所以容易想到状态压缩维护。

然后没了?

求大佬帮看代码 本地能跑但评测机上TLE
#include <bits/stdc++.h>
#define int long long
#define pii pair<int,int>
#define mp make_pair
using namespace std;
const int N=2e5+5;
const int MOD=1e9+7;
int n,q,a[N];
int prime[]={2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,101,103,107,109,113,127,131,137,139,149,151,157,163,167,173,179,181,191,193,197,199,211,223,227,229,233,239,241,251,257,263,269,271,277,281,283,293};
struct node{
	int l,r;//左右子树编号 
	int sum;//区间乘
	int tag1,tag2;//懒惰标记 
	int p;//质因子状压
}tr[N*4];
int inv[100],f[100];

int qsm(int x,int y)
{
	int res=1;
	while (y)
	{
		if (y&1){
			res=(res*x)%MOD;
		}
		y>>=1,x=(x*x)%MOD;
	}
	return res;
}
void push_up(int id)
{
	tr[id].sum=(tr[id<<1].sum*tr[(id<<1)+1].sum)%MOD;
	tr[id].p=tr[id<<1].p|tr[(id<<1)+1].p; 
}
void push_down(int id)
{
	int l=id<<1,r=(id<<1)+1;
	if (tr[id].tag1>1)
	{
		tr[l].sum=(tr[l].sum*qsm(tr[id].tag1,tr[l].r-tr[l].l+1))%MOD;
		tr[r].sum=(tr[r].sum*qsm(tr[id].tag1,tr[r].r-tr[r].l+1))%MOD;
		tr[l].tag1*=tr[id].tag1,tr[l].tag1%=MOD;
		tr[r].tag1*=tr[id].tag1,tr[r].tag1%=MOD;
	}
	if (tr[id].tag2)
	{
		tr[l].p|=tr[id].tag2,tr[l].tag2|=tr[id].tag2;
		tr[r].p|=tr[id].tag2,tr[r].tag2|=tr[id].tag2;
	}
	tr[id].tag1=1,tr[id].tag2=0;
}
void build(int id,int l,int r)
{
	tr[id].l=l,tr[id].r=r,tr[id].tag1=1;
	if (l==r)
	{
		tr[id].sum=a[l];
		for (int i=0;i<62;i++) if (a[l]%prime[i]==0) tr[id].p|=(1ll<<i);
		return ;
	}
	int mid=(l+r)>>1;
	build(id<<1,l,mid);
	build((id<<1)+1,mid+1,r);
	push_up(id);
}
void _update(int id,int l,int r,int x,int _p)
{
	if (l<=tr[id].l&&tr[id].r<=r)
	{
		tr[id].sum=(tr[id].sum*qsm(x,tr[id].r-tr[id].l+1))%MOD;
		tr[id].tag1*=x,tr[id].tag1%=MOD;
		tr[id].tag2|=_p,tr[id].p|=_p;
		return ;
	}
	push_down(id);
	int mid=(tr[id].l+tr[id].r)>>1;
	if (mid>=r) _update(id<<1,l,r,x,_p);
	if (mid<l) _update((id<<1)+1,l,r,x,_p);
	push_up(id);
}
pii _query(int id,int l,int r)
{
	if (l<=tr[id].l&&tr[id].r<=r) return mp(tr[id].sum,tr[id].p);
	pii res=mp(1,0);
	push_down(id);
	int mid=(tr[id].l+tr[id].r)>>1;
	if (mid>=r) 
	{
		pii a=_query(id<<1,l,r);
		res.first=(res.first*a.first)%MOD;
		res.second|=a.second;
	}
	if (mid<l) 
	{
		pii b=_query((id<<1)+1,l,r);
		res.first=(res.first*b.first)%MOD;
		res.second|=b.second;
	}
	return res;
}
signed main()
{
	scanf("%lld%lld",&n,&q);
	for (int i=1;i<=n;i++) scanf("%lld",&a[i]);
	
	build(1,1,n);
	inv[1]=1;
	for (int i=2;i<=300;i++) inv[i]=MOD-(MOD/i)*inv[MOD%i]%MOD;
	for (int i=0;i<62;i++) f[i]=inv[prime[i]]*(prime[i]-1)%MOD;
	
	char op[10];
	int l,r,x;
	while (q--)
	{
		scanf("%s",op);
		if (op[0]=='M')//区间乘 
		{
			scanf("%lld%lld%lld",&l,&r,&x);
			int p=0;
			for (int i=0;i<62;i++) if (x%prime[i]==0) p|=(1ll<<i);
			_update(1,l,r,x,p);
		}
		else
		{
			scanf("%lld%lld",&l,&r);
			pii ret=_query(1,l,r);//返回的乘积与质因子状态 
			int res=ret.first,phi=ret.second;//乘积,状态 
			for (int i=0;i<62;i++) if (phi&(1ll<<i)) res=(res*f[i])%MOD;
			printf("%lld\n",res%MOD);
		}
	}
	return 0;
}

标签:10,CF1114,tr,times,int,id,leqslant
From: https://www.cnblogs.com/Myyy-L/p/18563110

相关文章

  • CF1114F Please, another Queries on Array?
    一道很好的线段树+求欧拉函数题!!!先简单理解一下题意:给你一段长度为n的区间,q次操作,输入为1时将l~r区间每个数乘上x,输入为2时求解\(\varphi(\prod_{i=l}^{r}{a_i})\)。赛时心历经过:第一眼感觉是个线段树板子题,赛时也是这么想的,打到一半发现不对劲,首先这个乘积就没法维护,随便乘......
  • CF1114F Please, another Queries on Array?
    CF1114FPlease,anotherQueriesonArray?题目大意你有一个数组\(a_1,a_2,\dots,a_n\)。现在你需要完成\(q\)次操作,有以下两种操作形式:MULTIPLYlrx,对于所有\(i(......