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
*/