20170709训练赛比赛总结

B

反思
  • 由于C比较简单,我后写了B,写了一个多小时才发现我 DP 的状态定义臭(错)了。
思路
  • 我们发现对于一个区间 [l,r] ,我们需要从两端消去它,于是我们可以记录 [l,r] 的右边还需要几个才可以消去 A[r] ;
  • 于是 DP 的转移就很简单了,对于一个 [l,r] 我们可以补充它需要的个数把它变成 [l,r1]
  • 同时,我们可以把 [i,r1] 都消掉,把区间变成 [l,r1]
#include<bits/stdc++.h>
#define For(i,a,b) for(int i=a;i<=b;++i)
using namespace std;
const int M=105;
int dp[M][M][10],A[M],n,k;
/*dp[l][r][c]表示中消掉[l,r]这一段末尾的A[r]还需要c个*/    
int dfs(int l,int r,int c){
    if(l>r)return 0;
    int &ans=dp[l][r][c];
    if(~ans)return ans;
    /*于是我需要c次把A[r]消掉*/
    ans=dfs(l,r-1,k-1)+c;
    /*或者我们把中间开始某一段消掉即我们把[i+1,r-1]都消掉了,A[r]滚到了i+1,于是我们就只要c-1个了*/
    for(int i=l;i<r;i++)
        if(A[i]==A[r])ans=min(ans,dfs(l,i,max(c-1,0))+dfs(i+1,r-1,k-1));
    return ans;
}
int main(){
    memset(dp,-1,sizeof dp);
    scanf("%d %d",&n,&k);
    for(int i=1;i<=n;i++)scanf("%d",A+i); 
    printf("%d",dfs(1,n,k-1));
    return 0;
}
小结
  • DP 的定义和转移状态就是你的思路,千万不可以草率,一旦思路错误就难以挽救了。
  • DP 的定义过程中可以观察一下数据,本题 K<=5 的条件我根本没有使用,肯定有问题。。。

C

反思
  • 忘了加 longlong 。。。
  • 我们用的是歪解,用分块的。。。
#include<stdio.h>
const int M=1e6+5,S=50;
int cnt[M],n,m,x;
long long val[M];
void pri(long long x){
    if(!x)return;
    pri(x/10);
    putchar((x%10)+48);
}
void pt(long long ans){
    if(!ans)return;
    pri(ans);
}
int main(){
    scanf("%d %d",&n,&m);
    for(int i=1;i<=m;++i){
        scanf("%d",&x);
        if(x<=S)++cnt[x];
        else for(int i=0;i<n;i+=x)++val[i];
    }
    for(int i=0;i<n;++i)for(int j=1;j<=S;++j)if(cnt[j]&&i%j==0)val[i]+=cnt[j];
    for(int i=1;i<n;++i)val[i]+=val[i-1];
    scanf("%d",&m);
    while(m--){
        int x,y;
        scanf("%d %d",&x,&y);
        long long ans=val[y];
        if(x)ans-=val[x-1];
        pt(ans);putchar('\n');
    }
    return 0;
}
思路
  • 我们可以用类似于筛素数的方法来模拟
#include<bits/stdc++.h>
using namespace std;
const int M=1e6+5;
int n,m,A[M],y,x;
long long B[M];
int main(){
    scanf("%d%d",&n,&m);
    while(m--)scanf("%d",&x),A[x]++;
    for(int i=1;i<=n;i++)if(A[i])
        for(int j=0;j<=n;j+=i)B[j]+=A[i];

    for(int i=1;i<=n;i++)B[i]+=B[i-1];
    scanf("%d",&m);
    while(m--){
        scanf("%d%d",&x,&y);
        if(!x)printf("%lld\n",B[y]);
        else printf("%lld\n",B[y]-B[x-1]);
    }return 0;
}    
小结
  • longlong 一定不要忘了分析。
  • 遇到某些和算法模型相似的问题我们可以套用该算法的流程来分析。

D <script type="math/tex" id="MathJax-Element-935">D</script>

  • 见矩阵专题。。。
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值