Educational Codeforces Round 129 (Rated for Div. 2)
作者:互联网
真,自闭场
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