Codeforces Round # 633 (Div. 2) D (Conclusión) E (Ley + Estructura)

Enlace del título

No escribiré las primeras tres preguntas sobre el agua.

 

D. Asignación de peso de borde

Tema: le da un árbol que requiere que asigne valores para cada borde

 

Practica

A primera vista, esta pregunta es encontrar una conclusión, solo empujar unos cuantos árboles más y empujarlo.

Conclusión: la mejor estructura, cada peso de borde es diferente. Debido a que el poder lateral es infinito, debe haber algún esquema legal para hacer que el poder lateral sea XOR 0

Si la distancia entre dos nodos de hoja es igual a 2, la respuesta es uno menos

dfs construye los puntos con múltiples nodos hoja menos:

5-2 == 3

Entonces, ¿cómo construir el mínimo?

En el caso más pequeño, solo hay dos casos, 1 o 3

Cuando la distancia de todos los nodos de las hojas es par (el peso del borde es 1), todos los pesos de los bordes pueden ser iguales. La respuesta es 1

Cuando hay un nodo hoja, la distancia es 3 

En cuanto a cómo encontrar que la distancia entre una hoja es un número impar, usé un dp para cambiar la raíz

#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=(b);++i)
#define mem(a,x) memset(a,x,sizeof(a))
#define pb push_back
#define pi pair<int, int>
#define mk make_pair
using namespace std;
typedef long long ll;
ll gcd(ll a,ll b) { return b?gcd(b,a%b):a;}
const int N=1e5+10;
int dp[N][2],n;
vector<int>G[N];
int mi,mx,du[N],root;
void dfs1(int u,int fa)
{
    if(du[u]==1){
        dp[u][0]++;
        return ;
    }
    for(int v:G[u])
    {
        if(v==fa) continue;
        dfs1(v,u);
        dp[u][1]+=dp[v][0];
        dp[u][0]+=dp[v][1];
    }
}
void dfs2(int u,int fa)
{
    if(du[u]==1&&dp[u][1]) {
        mi=3;
        //printf("u:%d\n",u);
    }
    if(mi!=1) return ;
    for(int v:G[u])
    {
        if(v==fa) continue;
        int t0=dp[u][0];
        int t1=dp[u][1];
        dp[u][0]-=dp[v][1];
        dp[u][1]-=dp[v][0];
        dp[v][0]+=dp[u][1];
        dp[v][1]+=dp[u][0];
        dfs2(v,u);
        dp[u][0]=t0;
        dp[u][1]=t1;
    }
}
int dfs3(int u,int fa)
{
    int flag=0;
    for(int v:G[u])
    {
        if(v==fa) continue;
        flag+=dfs3(v,u);
    }
    if(flag>=2) mx-=flag-1;
    if(du[u]==1) return 1;
    return 0;
}
int main()
{
	cin>>n;
	rep(i,2,n)
	{
	    int u,v;
	    scanf("%d%d",&u,&v);
	    G[u].push_back(v);
	    G[v].push_back(u);
	    du[u]++;
	    du[v]++;
	}
	rep(i,1,n) if(du[i]>=2) root=i;

	dfs1(root,-1);
	mi=1;
	dfs2(root,-1);

	mx=n-1;
	dfs3(root,-1);
	printf("%d %d\n",mi,mx);
}

E. Triples perfectos

Tema: necesita construir un triplete de pequeño a grande y cada número es único y a ^ b ^ c = 0 está conectado a la parte posterior de la secuencia s en secuencia, ingrese n para averiguar cuál es el enésimo número

Práctica: escuche a los amigos del grupo decir que XOR y el cuaternario son buenos hermanos. Escriba la tabla según el título:

Programa de mesa de juego:

#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=(b);++i)
#define mem(a,x) memset(a,x,sizeof(a))
#define pb push_back
#define pi pair<int, int>
#define mk make_pair
using namespace std;
typedef long long ll;
ll gcd(ll a,ll b) { return b?gcd(b,a%b):a;}
const int N=1e5+10;
int vis[N];
void cal(int x)
{
    stack<int>sta;
    while(x)
    {
        int d=x%4;
        sta.push(d);
        x=x/4;
    }
    while(sta.size()) {
        printf("%d",sta.top());
        sta.pop();
    }
    printf(" ");
}
int main()
{
	rep(i,1,200)
	rep(j,1,200)
	rep(k,1,200){
        if(vis[i]||vis[j]||vis[k]) continue;
        if((i^j^k)==0){
             //cal(i),cal(j),cal(k);
             //puts("");
             printf("%d %d %d\n",i,j,k);
             vis[i]=1,vis[j]=1,vis[k]=1;
        }

	}
}


 

Parece que no hay regularidad

Cambiar a aspecto cuaternario:

Divida cada párrafo de acuerdo con la 4ª línea de alimentación:

1 2 3

10 20 30
11 22 33
12 23 31
13 21 32

100 200 300
101 202 303
102 203 301
103 201 302
110 220 330
111 222 333
112 223 331
113 221 332
120 230 310
121 232 313
122 233 311
123 231 312
130 210 320
131 212 323
132 213 321
133 211 322



1000 2000 3000
1001 2002 3003
1002 2003 3001
1003 2001 3002
1010 2030 3020
1020 2031 3011
1021 2032 3013
1023 2033 3010
1030 2022 3012

 

Encontré vagamente una regla, cada bit del triplete en cada segmento es 0 1 2 3 cambios, y el número de 0 1 2 3 consecutivos con el 4 actual

El número de decimales.

El segundo número de triples es 0 2 3 1 cambio.

El tercer número del triple es el cambio de 0 3 1 2.

Las reglas están ahí, pero parece muy problemático construir

También es problemático hablar y estudiar el código directamente:

Código de referencia de: código fuente

Primero encuentre que el número p del n actual está en una fila p de cierto segmento del triple y el primer elemento de la primera fila del segmento actual:

ll p=(n-1)/3,s=1,all=0;
while(p>=s)
{
    p-=s;
    s<<=2;
}

Según n% 3, encuentra el número en el triple.

En resumen: una muy buena regla y un muy buen método de construcción. .

 

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int main()
{
    int _;cin>>_;while(_--)
    {
        ll n;
        cin>>n;
		ll p=(n-1)/3,s=1,all=0;
		//当前n处在三元组 某一段中 某一行p  当前段第一行 第一个元素 的数字s:
        while(p>=s)
        {
            p-=s;
			s<<=2;
        }
        
        //p行对应的进制变化分别是0,1,2,3     0 2 3 1      0 3 2 1
        if(n%3==1) printf("%lld\n",s+p);//第一个数直接加
        else if(n%3==2)//第二个
        {
            ll ans=s<<1,c=1;//每一段的第一行是特殊的 x 2*x 3*x
            while(p)
            {
            	//四进制的最低位
                ll x=p%4;
                if(x==1) ans+=c*2;
                else if(x==2) ans+=c*3;
                else if(x==3) ans+=c;
                p>>=2,c<<=2;
            }
            printf("%lld\n",ans);
        }
        else
        {
            ll ans=s*3,c=1;
            while(p)
            {
                ll x=p%4;
                if(x==1) ans+=c*3;
                else if(x==2) ans+=c*1;
                else if(x==3) ans+=c*2;
                p>>=2,c<<=2;
            }
            printf("%lld\n",ans);
        }

    }
    return 0;
}

 

519 artículos originales publicados · elogiados 69 · 50,000+ vistas

Supongo que te gusta

Origin blog.csdn.net/qq_41286356/article/details/105506582
Recomendado
Clasificación