ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

并不对劲的CF1454D&E&F: Number into Simple Partition

2022-07-25 14:03:03  阅读:151  来源: 互联网

标签:CF1454D le Simple Partition times int ch include define


CF1454D: Number into Sequence

题目大意

给出一个正整数\(n\)(\(n>1\))。
你需要找出一个正整数序列\(a_1,a_2,...,a_k\)满足:
1.\(\forall i\in\{ 1,2,...,k\},a_i>1\);
2.\(a_1\times a_2\times ...\times a_k=n\);
3.\(\forall i\in \{1,2,..,k-1\},a_{i+1}\)能被\(a_i\)整除;
4.\(k\)尽可能大。
如果有多个答案,你可以输出任意一个。共\(t\)组询问。(\(1 \le t \le 5000;2\leq n\leq 10^{10}\),所有\(n\)之和不超过\(10^{10}\))

题解

将\(n\)分解质因数,得到\(n=c_1^{b_1}\times c_2^{b_2}\times ...\times c_m^{b_m}\)。
\(k\)最大不会超过质因数的指数中的最大值。
为了使\(k\)达到这个最大值,有一种构造方法是:
假设\(b_x=max(b_1,b_2,...,b_m)\),则\(a_1,a_2,...,a_{k-1}=c_x\),\(a_k=\frac{n}{c_x^{b_x-1}}\)

代码
#include<algorithm>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<ctime>
#include<iomanip>
#include<iostream>
#include<map>
#include<queue>
#include<set>
#include<stack>
#include<vector>
#define rep(i,x,y) for(register int i=(x);i<=(y);++i)
#define dwn(i,x,y) for(register int i=(x);i>=(y);--i)
#define view(u,k) for(int k=fir[u];~k;k=nxt[k])
#define LL long long
#define maxn 100007
using namespace std;
LL read()
{
	LL x=0;int f=1;char ch=getchar();
	while(!isdigit(ch)&&ch!='-')ch=getchar();
	if(ch=='-')f=-1,ch=getchar();
	while(isdigit(ch))x=(x<<1ll)+(x<<3ll)+ch-'0',ch=getchar();
	return x*f;
}
void write(LL x)
{
	if(x==0){putchar('0'),putchar('\n');return;}
	int f=0;char ch[20];
	if(x<0)putchar('-'),x=-x;
	while(x)ch[++f]=x%10ll+'0',x/=10ll;
	while(f)putchar(ch[f--]);
	putchar('\n');
	return;
}
void write_(LL x)
{
	if(x==0){putchar('0'),putchar('\n');return;}
	int f=0;char ch[20];
	if(x<0)putchar('-'),x=-x;
	while(x)ch[++f]=x%10ll+'0',x/=10ll;
	while(f)putchar(ch[f--]);
	putchar(' ');
	return;
}
LL n,p[maxn];
int t,no[maxn],cnt,lim=100000,a[maxn],b[maxn];
int main()
{
	no[1]=1;
	rep(i,2,lim)
	{
		if(!no[i])p[++cnt]=i;
		for(int j=1;j<=cnt&&(LL)i*p[j]<=(LL)lim;j++)
			no[i*p[j]]=1;
	}
	t=read();
	while(t--)
	{
		n=read();
		int nump=0,mx=(int)floor(sqrt((double)n)),mxp=0;
		rep(i,1,cnt)
		{
			if(p[i]>mx)break;
			if(n%((LL)p[i])==0)a[++nump]=p[i];
		}
		if(nump==0){write(1),write(n);continue;}
		rep(i,1,nump)
		{
			LL tmp=n;b[i]=0;
			while(tmp%((LL)a[i])==0)tmp/=a[i],b[i]++;
			if(mxp==0)mxp=i;
			else if(b[i]>b[mxp])mxp=i;
		}
		write(b[mxp]);LL tmpans=1;
		rep(i,1,b[mxp]-1)
		{
			tmpans*=(LL)a[mxp];
			write_(a[mxp]);
		}
		write_(n/tmpans);
		puts("");
	}
	return 0;
}

CF1454E: Number of Simple Paths

题目大意

给出一个\(n\)个点\(n\)条边的无重边无自环的连通无向图。
请求出该图中有多少条至少包括一条边的无向简单路径。有\(t\)组询问。
(\(1 \le t \le 2\times 10^4;3\le n\le 2\times 10^5\),且所有测试数据中\(n\)之和不超过\(2\times 10^5\))

题解

该图为接在同一个环上的很多树。
在每个树上计算出无向简单路径树。
在环上选两个点\(x,y\),经过这两个点的路径数等于\(以x为根的树的大小\times以y为根的树的大小\times 2\)。

代码
#include<algorithm>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<ctime>
#include<iomanip>
#include<iostream>
#include<map>
#include<queue>
#include<set>
#include<stack>
#include<vector>
#define rep(i,x,y) for(register int i=(x);i<=(y);++i)
#define dwn(i,x,y) for(register int i=(x);i>=(y);--i)
#define view(u,k) for(int k=fir[u];~k;k=nxt[k])
#define maxn 200007
#define maxm 400007
#define LL long long
using namespace std;
int read()
{
	int x=0,f=1;char ch=getchar();
	while(!isdigit(ch)&&ch!='-')ch=getchar();
	if(ch=='-')f=-1,ch=getchar();
	while(isdigit(ch))x=(x<<1)+(x<<3)+ch-'0',ch=getchar();
	return x*f;
}
void write(LL x)
{
	if(x==0){putchar('0'),putchar('\n');return;}
	int f=0;char ch[20];
	if(x<0)putchar('-'),x=-x;
	while(x)ch[++f]=x%10+'0',x/=10;
	while(f)putchar(ch[f--]);
	putchar('\n');
	return;
}
int vis[maxn],fir[maxn],nxt[maxm],v[maxm],cnte,ring,r[maxn],cntr,yesr[maxn];
int t,n;
LL f[maxn][5],ans,tmp;
void ade(int u1,int v1){v[cnte]=v1,nxt[cnte]=fir[u1],fir[u1]=cnte++;}
void adr(int u1){r[++cntr]=u1,yesr[u1]=1;}
void getr(int u,int fa)
{
	vis[u]=1;
	view(u,k)if(v[k]!=fa)
	{
		if(vis[v[k]])ring=v[k];
		else getr(v[k],u);
		if(ring!=0)break;
	}
	if(ring!=0&&ring!=-1)adr(u);
	if(ring==u)ring=-1;
}
void getf(int u,int fa)
{
	view(u,k)if(v[k]!=fa&&!yesr[v[k]])
	{
		getf(v[k],u);
		f[u][1]+=(f[u][0]+1)*(f[v[k]][0]+1ll);
		f[u][0]+=f[v[k]][0]+1ll;
	}
	ans+=f[u][1];
}
int main()
{
	t=read();
	while(t--)
	{
		n=read();ring=cnte=cntr=0;ans=0;
		rep(i,1,n)fir[i]=-1,vis[i]=yesr[i]=f[i][0]=f[i][1]=0;
		rep(i,1,n){int x=read(),y=read();ade(x,y),ade(y,x);}
		getr(1,0);
		rep(i,1,cntr)getf(r[i],0);tmp=0;
		rep(i,1,cntr)
		{
			ans+=(f[r[i]][0]+1)*tmp*2ll;
			tmp+=f[r[i]][0]+1;
		}
		write(ans);
	}
	return 0;
}

CF1454F: Array Partition

题目大意

给出一个\(n\)个正整数的数组\(a\)。
设\(min(l,r)\)(\(1\le l\le r\le n\))表示\(a_l,a_{l+1},...,a_r\)的最小值,\(max(l,r)\)(\(1\le l\le r\le n\))表示\(a_l,a_{l+1},...,a_r\)的最大值。
请找出三个正整数\(x,y,z\),满足:
1.\(x+y+z=n\);
2.\(max(1,x)=min(x+1,x+y)=max(x+y+1,n)\)。
如果有多组解,输出任意一组。
如果不存在符合条件的解,输出\(NO\)。
有\(t\)组询问。(\(1 \le t \le 2\times 10^4;3\le n\le 2\times 10^5\),且所有测试数据中\(n\)之和不超过\(2\times 10^5;1\le a_i\le 10^9\))

题解

\(x\)确定时,\(min(x+1,x+y)\)和\(max(x+y+1,n)\)有单调性。故可枚举\(x\),二分\(y\)。

代码
#include<algorithm>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<ctime>
#include<iomanip>
#include<iostream>
#include<map>
#include<queue>
#include<set>
#include<stack>
#include<vector>
#define rep(i,x,y) for(register int i=(x);i<=(y);++i)
#define dwn(i,x,y) for(register int i=(x);i>=(y);--i)
#define view(u,k) for(int k=fir[u];~k;k=nxt[k])
#define maxn 200007
#define maxb 21
using namespace std;
int read()
{
	int x=0,f=1;char ch=getchar();
	while(!isdigit(ch)&&ch!='-')ch=getchar();
	if(ch=='-')f=-1,ch=getchar();
	while(isdigit(ch))x=(x<<1)+(x<<3)+ch-'0',ch=getchar();
	return x*f;
}
void write(int x)
{
	if(x==0){putchar('0'),putchar('\n');return;}
	int f=0;char ch[20];
	if(x<0)putchar('-'),x=-x;
	while(x)ch[++f]=x%10+'0',x/=10;
	while(f)putchar(ch[f--]);
	putchar(' ');
	return;
}
int mna[maxn][maxb],a[maxn],n,t;
int bac[maxn],lim,mxa[maxn];
int getmn(int l,int r)
{
	int x=bac[r-l+1];
	return min(mna[l][x],mna[r-(1<<x)+1][x]);
}
int main()
{
	t=read();lim=18;
	lim=200000;int tmp=0;
	rep(i,1,lim)
	{
		if((1<<(tmp+1))<=i)tmp++;
		bac[i]=tmp;
	}
	while(t--)
	{
		n=read();
		rep(i,1,n)a[i]=read(),mna[i][0]=a[i];
		lim=0;while((1<<(lim+1))<=n)lim++;
		dwn(i,n,1)
			for(int k=1;i+(1<<k)-1<=n;k++)
				mna[i][k]=min(mna[i][k-1],mna[i+(1<<(k-1))][k-1]);
		mxa[n]=a[n];
		dwn(i,n-1,1)mxa[i]=max(mxa[i+1],a[i]);
		int ansx=-1,ansy=-1,mx=0;
		rep(x,1,n-1)
		{
			mx=max(a[x],mx);
			int l=x+1,r=n-1,ans=-1;
			while(l<=r)
			{
				int mi=((l+r)>>1);
				if(mx==mxa[mi+1])
				{
					int mn=getmn(x+1,mi);
					if(mn==mx){ans=mi;break;}
					else if(mn<mx){r=mi-1;}
					else l=mi+1;
				}
				else if(mxa[mi+1]<mx)r=mi-1;
				else l=mi+1;
			}
			if(ans!=-1){ansy=ans-x,ansx=x;break;}
		}
		if(ansx==-1)puts("NO");
		else
		{
			puts("YES");
			write(ansx),write(ansy),write(n-ansx-ansy);puts("");
		}
		dwn(i,n,1)
			for(int k=1;i+(1<<k)-1<=n;k++)
				mna[i][k]=0;
	}
	
	return 0;
}

标签:CF1454D,le,Simple,Partition,times,int,ch,include,define
来源: https://www.cnblogs.com/xzyf/p/16517163.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有