百度之星初赛 A

HDU 5693

在当前剩下的有序数组中选择X(X2)X(X≥2) 个连续数字;  

1  看题目要注意后面几个字 

要不就是删2 个要不就是删3个    3个以上可以由  2   3 组成     GGG

然后就是区间DP  dp[i][j]  代表 从i 到 j  最多可以删除几个 

然后呢      dp[i][j]   =      max ( dp[i][j],          1             w[i]  代表第i  个权值 

1   如果 dp[i+1][j-1]  == j-1 -(i+1) +1    &&w[i]  w[j] 是等差        dp[i+1][j-1]  +2  

2    dp[i][k]+dp[k+1][r];

3     dp[i+1][k-1] +dp[k+1][j-1]   然后 w[i] w[k] w[j]   是等差 然后 dp[] []  dp[][]   要都是满的  反正都写上去就行了  

#include<stdio.h>
#include<algorithm>
#include<stdlib.h>
#include<cstring>
#include<string>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
using namespace std;

#define LL   __int64
#define MAXN 310
#define inf  1000000000

int w[MAXN];
int d[MAXN];
int dp[MAXN][MAXN];
int vis[MAXN][MAXN];

int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        int n,m;
        scanf("%d%d",&n,&m);
        memset(dp,0,sizeof(dp));
        memset(vis,0,sizeof(vis));
        for(int i=1;i<=n;i++)
            scanf("%d",&w[i]);
        for(int i=1;i<=m;i++)
            scanf("%d",&d[i]);
        for(int i=1;i<=n;i++)
        {
            for(int j=i+1;j<=n;j++)
            {
                for(int k=1;k<=m;k++)
                {
                    if(w[j]-w[i]==d[k])
                        vis[i][j]=1;
                }
            }
        }
        for(int len=1;len<=n;len++)
        {
            for(int l=1;l<=n;l++)
            {
                int r=l+len;
                if(r>n)
                    break;
                dp[l][r]=max(dp[l][r-1],dp[l+1][r]);
                if(vis[l][r]&&dp[l+1][r-1]==r-l-1)
                    dp[l][r]=max(dp[l][r],dp[l+1][r-1]+2);
                for(int i=l;i<r;i++)
                    dp[l][r]=max(dp[l][i]+dp[i+1][r],dp[l][r]);
                for(int i=l+1;i<r;i++)
                {
                    if(vis[l][i]&&dp[l+1][i-1]==i-l-1)
                        dp[l][r]=max(dp[l][r],dp[l+1][i-1]+2+dp[i+1][r]);
                    if(vis[i][r]&&dp[i+1][r-1]==r-i-1)
                        dp[l][r]=max(dp[l][r],dp[l][i-1]+dp[i+1][r-1]+2);
                    if(vis[l][i]&&vis[i][r]&&w[r]-w[i]==w[i]-w[l]&&dp[l+1][i-1]==i-l-1&&dp[i+1][r-1]==r-i-1)
                        dp[l][r]=max(dp[l][r],r-l+1);
                }
            }
        }
        printf("%d
",dp[1][n]);
    }
    return 0;
}
View Code

HDU 5694 

要考虑对称 的情况  cnt[i]  代表这个串的长度  那么 这个整串  里肯定由  cnt[i-1]+1 个B     然而并没什么用

其实就是考虑  len  <cnt[i] &&>cnt[i-1]的情况  那么  假设 len = 12 

BB D BBDD  B  BBDD BDD

                             len

到中间的B  右边4  个和 左边 4  个  左边 4个取反后应该是对称的   那么   4  - 12 的 B  应该是  len -cnt[i-1]-1   加上中间的 就是  len-cnt[i-1]

然后再计算出长度为  cnt[i] -  len的     递归一下 

#include<stdio.h>
#include<algorithm>
#include<stdlib.h>
#include<cstring>
#include<string>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
using namespace std;

#define ll   __int64
#define MAXN 70
#define inf  1000000000
ll cnt[MAXN];

ll calc(ll x)
{
    if(x==0)
    return 0;
    ll sum=0;

    for(int i=1;i<MAXN;i++)
    {
        if(cnt[i]==x)
            return cnt[i-1]+1;

        if(cnt[i]>x)
        {
            sum +=x-cnt[i-1];
            return sum+calc(cnt[i]-x);
        }
    }
}

int main()
{
    int t;
    scanf("%d",&t);
    cnt[1]=1;
    for(int i=2;i<MAXN;i++)
        cnt[i]=2*cnt[i-1]+1;

    while(t--)
    {
        ll  l,r;
        scanf("%I64d%I64d",&l,&r);
        printf("%I64d
",calc(r)-calc(l-1));
    }
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/cherryMJY/p/6596290.html