AtCoder Beginner Contest 162 (E (enumeración matemática gcd) F (elija n / 2 número dp))

Enlace del título

Las primeras cuatro preguntas son preguntas sobre el agua.

Ven a ver E

E - Suma de mcd de Tuplas (Difícil)

Tema:

Darle n y k requiere que encuentre la suma de mcd en todas las combinaciones de secuencia.

Hay un total de secuencias K ^ n

 

Práctica: Una obvia es enumerar gcd, y luego calcular la respuesta,

mcd = 1 => Plan: k ^ n

mcd = 2 => (k / 2) ^ n

Eliminar el doble cálculo:

1.gcd = 1-> gcd1-gcd2-gcd3 ....

2.gcd = 2-> gcd2-gcd4-gcd6 ...

3.gcd = 3> gcd3-gcd6-gcd9 ...

Pero de 1 enumeración a k, se debe considerar la tolerancia.

La enumeración al revés es innecesaria

 

#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 ll mod=1e9+7;
ll powmod(ll a,ll b) {ll res=1;a%=mod;
assert(b>=0); for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}
const int N=1e5+10;
ll n,k;
ll dp[N];
void add(ll &x,ll y)
{
    x=(x+y)%mod;
}
int main()
{

    cin>>n>>k;

    ll ans=0;
    for(ll gc=k;gc;--gc)
    {
        ll di=k/gc;
        ll num=powmod(di,n)%mod;
        ll t=0;
        for(ll j=gc+gc;j<=k;j+=gc) add(t,dp[j]);
    
        dp[gc]=(num-t+mod)%mod;
    }

    for(int i=1;i<=k;++i){
        add(ans,dp[i]*i%mod);
    }
    cout<<ans<<endl;
}
/*
3 200
*/

 

F - Seleccione la mitad

Tema: Darle una secuencia de n longitud a [i] Ahora debe elegir n / 2 (redondear hacia abajo) a [i] y no puede tomar los números adyacentes, haciendo que el número seleccionado sea lo más grande posible.

Como n tiene 1e5, no puede abrir dp bidimensional

Práctica: la práctica se refiere al código de otras personas

Probablemente el valor máximo legal de dp [i] antes de que se mantenga dp [i].

Elija x cada vez en la posición actual I. Elija de la posición x-1 y combine las características que no pueden ser adyacentes.

 

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 2e5 + 5;
ll dp[N][2],a[N];
void solve()
{
	int n;
	cin >> n;

	for (int i = 1; i < n + 1; i++)
		cin >> a[i];
	memset(dp, 0, sizeof(dp));
	dp[2][1] = a[2];
	dp[2][0] = a[1];
	for (int i = 3; i < n + 1; i++)
	{
		if (i & 1)
		{
			ll temp = max({dp[i-3][1],dp[i-3][0],dp[i-2][1],dp[i-2][0]});
			//位置i选择
			//i:x个
			//i-1 x个
			//i-2:x-1个
			//i-3:x-1个
			//i-4: x-2个
			dp[i][1] = a[i] + temp;

			dp[i][0]=max({dp[i-1][1],dp[i-1][0],a[i-2]+dp[i-3][0]});
			//arr[i-3]+dp[i-2][1] :不合法
			//该位置不选,从x继承dp[i-1]
			//i-1:x个
			//i-2:x-1个
			//i-3: x-1个
		}
		else
		{
			dp[i][1]=a[i]+max({dp[i-2][1],dp[i-2][0],dp[i-1][0]});
			//选当前位置 x=i/2
			//i-1:x-1个
			//i-2:x-1个


			//位置i不选,从x位置转移 由于没有x位置
			//i-1:x-1个
			//i-2 x-1个
			//i-3:x-2个
			//结论:一定选i-1  维护前i个必须选i/2个的特性
			dp[i][0] = a[i-1]+dp[i-2][0];
		}
	}
	cout << max(dp[n][1], dp[n][0]) << endl;
	return;
}

int main()
{
	solve();
	return 0;
}
/*
没有两个相邻的被选上
8
1 2 3 4 -1 -2 -3 -4
*/

 

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

Supongo que te gusta

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