Educational Codeforces Round 83 (Rated for Div. 2)(D(计数题)E(区间dp))

题目链接

D. Count the Arrays

题意:输入n,m  要你构造n长度的序列,每个数是在1~m 其中有一对数要相同,其他数不相同,并且有个峰值点,就是左边是递增,右边是递减的,问能构造多少个这样的序列

做法:

写的不错,偷过来  来自

#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=998244353;

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;}
ll n,m;

int main()
{
    printf("%d\n",(0^0));
	scanf("%lld%lld",&n,&m);
	if(n==2){
        puts("0");
        return 0;
	}
    ll ans=0,t=1;
    for(ll i=n-1;i<=m;i++)
    {
        ans=(ans+(i-1)*t%mod*powmod(2,n-3)%mod)%mod;

        t=t*(i-1)%mod;

        t=t*powmod(i-n+2,mod-2)%mod;
    }
    printf("%lld\n",ans);
	return 0;
}

E. Array Shrinking

题意:每次可以选择两个相邻的数并且相等的数进行消除,并且用x+1替代,问最后这个序列最短是多少

做法:一眼区间dp模板题

#include<bits/stdc++.h>
using namespace std;
const int N=5e2+10;
int dp[N][N],vis[N][N];
int n,a[N];
int main()
{
    for(int i=1;i<N;++i)
    for(int j=1;j<N;++j) dp[i][j]=1e9,vis[i][j]=-1;
    scanf("%d",&n);
    for(int i=1;i<=n;++i){
        scanf("%d",&a[i]);
        vis[i][i]=a[i];
        dp[i][i]=1;
    }

    for(int len=2;len<=n;++len){
        for(int l=1;l+len-1<=n;++l){
            int r=l+len-1;
            for(int k=l;k<=r-1;++k){
                if(dp[l][r]<dp[l][k]+dp[k+1][r]-1) continue;
                if(vis[l][k]==-1||vis[k+1][r]==-1||vis[l][k]!=vis[k+1][r]) {
                    dp[l][r]=min(dp[l][r],dp[l][k]+dp[k+1][r]);
                    continue;
                }


                dp[l][r]=dp[l][k]+dp[k+1][r]-1;
                vis[l][r]=vis[l][k]+1;

            }
        }
    }
    printf("%d\n",dp[1][n]);
}
发布了498 篇原创文章 · 获赞 66 · 访问量 4万+

猜你喜欢

转载自blog.csdn.net/qq_41286356/article/details/104775974