ICode9

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

Educational Codeforces Round 129 (Rated for Div. 2)

2022-07-13 10:32:22  阅读:132  来源: 互联网

标签:Educational Rated int ll Codeforces long -- ans DP


真,自闭场
C题已经忘记是什么了,记得一开始的做法不知道错哪了,最后改了个做法才过
D原本一直在想有什么数论上的性质和结论,一直局限于乘的那个数的选择,没有从因数的角度考虑,于是自闭
F最后看了下感觉可做,后来发现确实不难

D

其实本质是从搜索的角度出发,然后考虑状态的数量:只要发现每个状态都是x与一些小于10的数相乘,就可以直接记录乘的数的2,3,5,7的次幂,然后直接DP即可。
原本写了个四维DP,觉得代码量不像1700的题,后来看题解发现BFS会短很多(甚至不需要记录次幂,就直接单位边权图的最短路即可)
因为可DP的充要条件是状态转移满足拓扑序,所以在一些形式上不是DAG但本质是DAG,但直接用数组又比较麻烦的题上,可以直接BFS会好写很多!
(当时其实有尝试写个记忆化搜索,但心态较崩且觉得不对就没调完,其实是可以过的...)

垃圾DP版代码

#include<bits/stdc++.h>
using namespace std;
typedef unsigned long long ll;
const int N=65;
void Min(int& a,int b){
	a=min(a,b);
}
ll n,m,x;
int a[5]={0,2,3,5,7},b[5],d[11][5];
int f[N][N][N][N];
int main()
{
	cin>>n>>x;
	m=1; n--;
	while(n--) m*=10;
	for(int i=1;i<=4;i++) b[i]=log(m/x)/log(a[i])+3;
	d[2][1]=d[3][2]=d[5][3]=d[6][1]=d[6][2]=d[7][4]=1;
	d[4][1]=d[9][2]=2;
	//!!! a[2]=3->d[9][2]!!!
	d[8][1]=3;
	memset(f,0x3f,sizeof(f));
	f[0][0][0][0]=0;
	int c[5]={0},ans=1e9;
	for(c[1]=0;c[1]<=b[1];c[1]++){
		for(c[2]=0;c[2]<=b[2];c[2]++){
			for(c[3]=0;c[3]<=b[3];c[3]++){
				for(c[4]=0;c[4]<=b[4];c[4]++){
					if(f[c[1]][c[2]][c[3]][c[4]]>1e9) continue;
					ll s=x;
					bool p=(s>=m);
					for(int u=1;u<=4;u++){
						for(int v=1;v<=c[u];v++){
							if(s>m/a[u]){
								p=1;
								break;
							}
							s*=a[u];
						}
						if(p) break;
					}
					if(p || s>=m){
						ans=min(ans,f[c[1]][c[2]][c[3]][c[4]]);
						continue;
					}
					//printf("s=%lld f=%d\n",s,f[c[1]][c[2]][c[3]][c[4]]);
					//for(int i=1;i<=4;i++) cout<<c[i]<<" "; puts("");
					while(s){
						int t=s%10;
						Min(f[c[1]+d[t][1]][c[2]+d[t][2]][c[3]+d[t][3]][c[4]+d[t][4]],f[c[1]][c[2]][c[3]][c[4]]+1);
						//cout<<"t="<<t<<endl;
						s/=10;
					}
				}
			}
		}
	}
	if(ans>=1e9) puts("-1");
	else cout<<ans<<endl;
	return 0;
}

F

一开始先想每条边的贡献,然后是一个类似换根DP的问题,可能需要线段树合并维护,感觉不太友善。
然后想到,边权相同的边的贡献一起考虑,这就是一个类似于虚数的东西,建出来之后直接计算即可。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=5e5+5;
int n,hd[N],to[N<<1],nx[N<<1],wl[N<<1],tt;
void add(int u,int v,int w){
	nx[++tt]=hd[u];
	to[hd[u]=tt]=v;
	wl[tt]=w;
}
int fa[N],fx[N],dn[N],sz[N],ct;
void dfs(int u){
	sz[u]=1;
	dn[u]=++ct;
	for(int e=hd[u];e;e=nx[e]) if(to[e]!=fa[u]){
		int v=to[e];
		fa[v]=u; fx[v]=wl[e];
		dfs(v);
		sz[u]+=sz[v];
	}
}
bool cmp(int x,int y){
	return dn[x]<dn[y];
}
vector<int>h[N];
int f[N],g[N],q[N];
ll ans;
int main()
{
	cin>>n;
	for(int u,v,x,i=1;i<n;i++) scanf("%d%d%d",&u,&v,&x),add(u,v,x),add(v,u,x);
	dfs(1);
	for(int i=2;i<=n;i++) h[fx[i]].push_back(i);
	for(int i=1;i<=n;i++){
		int z=h[i].size();
		if(!z) continue;
		sort(h[i].begin(),h[i].end(),cmp);
		//printf("i=%d z=%d\n",i,z);
		g[z]=n;
		f[z]=0;
		q[0]=z;
		int t=0;
		for(int j=0;j<z;j++){
			int u=h[i][j];
			//cout<<"u="<<u<<endl;
			while(t && dn[u]>=dn[h[i][q[t]]]+sz[h[i][q[t]]]) t--;
			f[j]=q[t];
			g[j]=sz[u];
			g[q[t]]-=g[j];
			q[++t]=j;
		}
		for(int i=0;i<z;i++) ans+=1ll*g[i]*g[f[i]];
	}
	cout<<ans<<endl;
	return 0;
}

标签:Educational,Rated,int,ll,Codeforces,long,--,ans,DP
来源: https://www.cnblogs.com/szsz/p/16472909.html

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

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

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

ICode9版权所有