Codeforces Round 856 (Div. 2)(C,D)
Codeforces Round 856 (Div. 2)(C,D)
C
这个题的大意就是给你\(n\)个非递减的数,然后我们对于一个数组,这个数组的价值是这样定义的
那么我们需要知道对于从\(i\)和\(k\)这一段的数组的子数组,使得价值最大
对于这一价值的更大化,我们优先选择那些较大的,我们需要判断的就是此时的最小的是否是可以让价值变较大的,如果此时最小的数\(mi\)小于此时的长度,那么比起上一轮的最大价值\(value\),此时的价值\(value_{now}=value\times \frac{a_{now}}{len}\),就变得比上一轮更小了,明显不划算
然后这个原来的数组就是一个非递减的数组,所以对于此时的最小值就是上一轮最优子序列的最前面一个数
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
const int maxn=2e5+10;
int t,n;
int a[maxn];
int ans[maxn];
void solve()
{
cin>>n;
int l=1;
for (int i=1;i<=n;i++)
{
cin>>a[i];
while (l<i&&a[l]<(i-l+1))
{
l++;
}
ans[i]=max(1,i-l+1);
}
for (int i=1;i<=n;i++)
{
cout<<ans[i]<<" ";
}
cout<<'\n';
return ;
}
signed main ()
{
cin>>t;
while (t--)
{
solve();
}
system ("pause");
return 0;
}
D
这个题的大意就是给你\(2n\)个数,然后我们需要知道这\(2n\)个数可以组成多少个数
这个组成方式是以质数的幂次相乘的形式组成的,如,此时有一个\(m\)
以上面的这种形式
一个一个构造显然是不太行的
所以我们可以对于每一个\(p_i^{ei}\)一个一个单独来看
对于第\(i\)对\(p_i^{ei}\)的不同组成,从而得知最后得到的\(m\)有多少种
那么对于每一个数\(x\),有\(y\)个,那么求\(dp[i]\)选择\(i\)个底数,并且我们已经把\(sum\)个数的位置已经安排好了
假如\(x\)是作为幂次的,那么我们可以从剩余的幂次位置还有\(n-(sum-i)\)个,我们从这些位置中选择\(y\)个位置分配
假如\(x\)可以作为底数,那么我们从这\(y\)个里面拿出一个作为第\(i\)个底数,然后其他的\(y-1\)个需要从剩余的幂次位置(\(n-(sum-(i-1))\)中选择
由于每个质数都只能作为底数最多一次,所以,对于同样的数,分配在不同的位置,那么对于每一个质数都是不同的效果,那么最后的值都是不一样的,因为质数是不可以由其他数转换而来的,这就是为什么要通过每一个数的位置分配来计算\(m\)的数量
然后具体的就看代码吧
#include <iostream>
#include <string>
#include <algorithm>
#include <map>
#include <vector>
using namespace std;
const int maxn=4044+10;
const int N=1e6+10;
const int mod=998244353;
#define int long long
int t,n;
int a[maxn];
int f[maxn],invf[maxn];
bool is[N];
int p[N],cnt;
int dp[maxn];
int ksm(int x,int p)
{
int res=1;
while (p)
{
if (p&1)
{
res=(res*x)%mod;
}
x=(x*x)%mod;
p>>=1;
}
return res%mod;
}
void init()
{
int mx=4044;
f[0]=f[1]=1;
for (int i=2;i<=mx;i++)
{
f[i]=f[i-1]*i%mod;
}
invf[mx]=ksm(f[mx],mod-2);
for (int i=mx-1;i>=0;i--)
{
invf[i]=1ll*invf[i+1]*(i+1ll)%mod;
}
return ;
}
int C(int n,int m)
{
if (n==m&&m==-1) return 1;
if (n<0||m<0) return 0;
return f[n]*invf[n-m]%mod*invf[m]%mod;
}
void prime()
{
for (int i=2;i<N;i++)
{
if (!is[i]) p[++cnt]=i;
for (int j=1;j<=cnt&&i*p[j]<N;j++)
{
is[i*p[j]]=true;
if (i%p[j]==0) break;
}
}
is[1]=true;//!is[x]代表x是质数,1不是质数
return ;
}
void solve()
{
cin>>n;
map<int,int>cnt;
for (int i=1;i<=2*n;i++)
{
cin>>a[i];
cnt[a[i]]++;
}
int sum=0;
vector<int>dp(n+1,0);
dp[0]=1;
for (auto [x,y]:cnt)
{
vector<int>ndp(n+1,0);
for (int i=0;i<=n;i++)
{
ndp[i]=(ndp[i]+dp[i]*C(n-(sum-i),y)%mod)%mod;
if (i>=1&&!is[x])
{
ndp[i]=(ndp[i]+dp[i-1]*C(n-(sum-(i-1)),y-1)%mod)%mod;
}
}
sum+=y;
dp=ndp;
}
cout<<dp[n]<<'\n';
return ;
}
signed main ()
{
t=1;
init();
prime();
while (t--)
{
solve();
}
system ("pause");
return 0;
}

浙公网安备 33010602011771号