Concurso para iniciantes AtCoder 162 (E (enumeração matemática gcd) F (escolha número n / 2 dp))

Link do título

As quatro primeiras perguntas são perguntas sobre a água.

Venha ver E

E - Soma do MDC de Tuplas (Difícil)

Tópico:

Dar n e k requer que você encontre a soma de gcd em todas as combinações de seqüências.

Há um total de seqüências K ^ n

 

Prática: Um óbvio é enumerar o MDC e calcular a resposta,

gcd = 1 => Plano: k ^ n

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

Remova o cálculo duplo:

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

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

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

Mas de 1 enumeração para k, deve-se considerar a tolerância.

A enumeração para trás é desnecessária

 

#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 - Selecione metade

Tópico: Dê a você uma sequência de n comprimento a [i] Agora você deve escolher n / 2 (arredondar para baixo) a [i] e não poderá usar os números adjacentes, tornando o número selecionado o maior possível.

Como n tem 1e5, ele não pode abrir dp bidimensional

Prática: Prática refere-se ao código de outras pessoas

Provavelmente, o valor máximo legal de dp [i] antes de dp [i] é mantido.

Escolha x cada vez na posição atual I. Escolha na posição x-1 e combine os recursos que não podem ser adjacentes.

 

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

 

Publicado 519 artigos originais · elogiou 69 · 50.000+ visualizações

Acho que você gosta

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