题目链接
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]);
}