7-12 子序列(2023郑州轻工业大学校赛
Posted Demoo.
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了7-12 子序列(2023郑州轻工业大学校赛相关的知识,希望对你有一定的参考价值。
题意:
有一个长度为n的子序列,第i个数为a[i]
求不超过三对位置的元素相等的子序列的个数
思路:
对于每个数,我们先存他有几个位置
然后我们再遍历每种数:
设数x的不同位置有y个
dp[i]表示所选的序列恰好有i对相等的数的序列的个数
dp[0]表示所选序列中恰好有0对相同的数的序列的个数,那么我们在之前的所有的序列之后选上x这个数或者不选x这个数之后,所选的序列依旧是有0对相同的数,有因为x这个数有y种位置,所以我们有y+1种选法,即:
dp[0]=dp[0]*(y+1)
dp[1]表示所选序列中恰好有1对相同的数的序列个数
那么由两部分组成:
1.在之前序列中相同的数为0对的序列的基础上,再选一对相同的x(在y个位置里选两个),即dp[0] *
C
y
2
C_y^2
Cy2;
2.在之前序列中相同的数为1对的序列的基础上,再选一个x,或者不选x,即dp[1] *(y+1)
dp[2]表示所选序列中恰好有两对相同的数的序列的个数
那么由两部分组成:
1.在之前相同数的对数为1的序列的基础上,再选一对相同的x(在y个位置里选两个),即dp[1] *
C
y
2
C_y^2
Cy2;
2.在之前序列中相同的数为两对的序列的基础上,再选一个x,或者不选,即dp[2] *(y+1)
dp[3]表示所选序列中恰好有三对相同的数的序列的个数
那么由三部分组成:
1.在之前相同数的对数为0的基础上选三对相同的x(在y个位置中选三个),即dp[0] *
C
y
3
C_y^3
Cy3;
2.在之前相同数对数为2的序列的基础上选一对相同的x(在y个位置里选两个),即dp[2] *
C
y
2
C_y^2
Cy2
3.在之前相同数对数为3的序列的基础上选一个x或者不选x,即dp[3] *(y+1)
#include<bits/stdc++.h>
#include<vector>
#define int long long
using namespace std;
const int N=2e5+10;
const int mod=998244353;
typedef long long ll;
int n,m;
int a[N];
ll dp[N][6];
int f[N],fi[N];
int ksm(int a,int b)
int res=1%mod;
while(b)
if(b&1)res=res*a%mod;
a=a*a%mod;
b>>=1;
return res;
void init()
f[0]=fi[0]=1;
for(int i=1;i<N;i++)
f[i]=(f[i-1]*i)%mod;
fi[i]=(fi[i-1]*ksm(i,mod-2))%mod;
signed main()
scanf("%lld",&n);
init();
map<int,int> mp;
vector<int> op;
op.push_back(0);
for(int i=1;i<=n;i++)
scanf("%lld",&a[i]);
mp[a[i]]++;
op.push_back(a[i]);
sort(op.begin(),op.end());
op.erase(unique(op.begin(),op.end()),op.end());
dp[0][0]=1;
for(int i=1;i<op.size();i++)
int y=mp[op[i]];
dp[i][3]=dp[i-1][3]%mod*(y+1)%mod;
if(y>=2)
dp[i][3]=(dp[i][3]+dp[i-1][2]%mod*(f[y]*fi[2]%mod*fi[y-2]%mod)%mod)%mod;
if(y>=3)
dp[i][3]=(dp[i][3]+dp[i-1][0]%mod*(f[y]*fi[3]%mod*fi[y-3]%mod)%mod)%mod;
dp[i][2]=(dp[i-1][2]%mod*(y+1))%mod;
if(y>=2)
dp[i][2]=(dp[i][2]%mod+dp[i-1][1]*(f[y]*fi[2]%mod*fi[y-2]%mod)%mod)%mod;
dp[i][1]=(dp[i-1][1]%mod*(y+1)%mod)%mod;
if(y>=2)
dp[i][1]=(dp[i][1]%mod+dp[i-1][0]*(f[y]*fi[2]%mod*fi[y-2]%mod)%mod)%mod;
dp[i][0]=dp[i-1][0]*(y+1)%mod;
ll ans=0;
int len=op.size();
for(int i=0;i<=3;i++)
ans=(ans%mod+dp[len-1][i]%mod)%mod;
cout<<ans-1;//减掉一个空字符
return 0;
7-8 what‘s 莫比乌斯最大值(2023郑州轻工业大学校赛
题意:
有n个问题和闲聊
问题的格式是’what’s + S 问题 S_问题 S问题’
闲聊的格式是 S 问题 S_问题 S问题+ S 回答 S_回答 S回答, S 问题 S_问题 S问题的长度>=0
对于每个 S 回答 S_回答 S回答 ,只能回答在这句话之前提问的问题
那么求最多能回答几个不同的问题
思路:
对于每个回答,他的每个前缀都可能是一个出现过的问题
那么我们对于一个回答,让他贪心的回答出现过的前缀最长的问题
因为对于一个回答,如果他的长度长,可以回答长度长的问题和长度短的问题,如果他的长度短的话就只能回答长度短的问题,所以我们优先让他回答没有回答过的长度最长的问题
用umap来记录一个问题是否出现过,以及是否被回答过。
注意:
加了ios::sync_with_stdio(false)就不能用getchar(),需要用cin.get()
对于map的每次询问都是插入,如果对于每出现过的map,需要先判断是否出现过载判断值,可以节省时间防止tle
#include<bits/stdc++.h>
using namespace std;
const int N=4e6+10;
int idx,n;
int main()
ios::sync_with_stdio(false);
cin.tie(),cout.tie();
cin>>n;
cin.get();//加了ios不能用getchar
unordered_map<string,int> chuxian;//记录是否被回答过,如果等于0就是没有
unordered_map<string,int> huida;
int con=0;
for(int i=1;i<=n;i++)
string s;
cin>>s;
if(s=="what's")
cin>>s;
chuxian[s]=1;
else
string op;
int id=-1;
string ans;
for(int i=0;i<s.size();i++)
op+=s[i];
if(chuxian.count(op)&&chuxian[op]==1&&huida.count(op)==0)
id=i;
ans=op;
if(id!=-1)
huida[ans]=1;
con++;
cout<<con;
return 0;
以上是关于7-12 子序列(2023郑州轻工业大学校赛的主要内容,如果未能解决你的问题,请参考以下文章