寒假训练赛01补题
昨天是寒假训练赛第一场,A了两题,rank34。打的一般。最近做的题确实比较少了,得加强训练。
A.新年礼物
签到+模拟
思路:直接遍历一遍,每次更新手中灯笼的漂亮值和价值,然后计数即可。
代码:
LL p[N],w[N];
void solve(){
int n;
cin>>n;
for(int i=0;i<n;i++) cin>>p[i];
for(int i=0;i<n;i++) cin>>w[i];
int cnt=0,cp=p[0],cw=w[0];
for(int i=1;i<n;i++){
if(p[i]>cp){
cp=p[i];
if(cw>w[i]) cnt++;
cw=w[i];
}
}
cout<<cnt<<endl;
}
B.灯笼展
题意:对于第i个数,求出前面的数中小于等于该数的第k个数。
思路:因为每次要求的k都是固定的,所以我们只需要去维护第k大的数即可。赛时调试了很久,后面想出直接可以用优先队列(大根堆)去维护即可。
代码:
LL a[N];
void solve(){
int n,k;
cin>>n>>k;
priority_queue<int> q;
for(int i=0;i<n;i++) cin>>a[i];
for(int i=0;i<k;i++){
q.push(a[i]);
cout<<-1<<endl;
}
for(int i=k;i<n;i++){
if(a[i]>=q.top()) cout<<q.top()<<endl;
else {
cout<<-1<<endl;
q.pop();
q.push(a[i]);
}
}
}
C.新年大礼
二分
题意:在1-n的序列中删去几个值,问你现在第k个数是多少?
思路:二分找出满足
k
+
p
o
s
>
a
p
o
s
k+pos>a_{pos}
k+pos>apos的最大值。
代码:
void solve(){
int n,m;
cin>>n>>m;
vector<LL> a(n);
for(int i=0;i<n;i++) cin>>a[i];
sort(all(a));
while(m--){
LL k;
cin>>k;
int l=0,r=n;
while(l<r){
int mid=l+r>>1;
if(k+mid+1>a[mid]) l=mid+1;
else r=mid;
}
cout<<k+l<<endl;
}
}
D.摩天楼
模拟+单链表
题意:给你三种操作1.ADD 加一个数到栈顶 2.REMOVE 去除栈顶的元素(如果还有数的话) 3.LOAD 回到t时刻。
思路:前两种操作只需要去维护单链表尾部的数即可。而第三种操作,我们则需要用一个数组去存每个状态的指针。便于我们回到那个时候。
代码:
struct node{
int val;
node *pre;
};
void solve(){
node *root=new (node){-1,0};
auto cur=root;
int n;
cin>>n;
vector<node*> a(n+1);
for(int i=1;i<=n;i++){
string op;
int x;
cin>>op;
if(op[0]!='R') cin>>x;
if(op[0]=='A') cur=new (node){x,cur};
else if(op[0]=='R'){
if(cur->pre) cur=cur->pre;
}
else if(op[0]=='L') cur=a[x];
a[i]=cur;
cout<<cur->val<<endl;
}
}
E.神抽
题意:有n个卡池,每个卡池中有k个(k不同)角色,告诉你每个角色下赛季要去的卡池,如果先抽到任何一个卡池中的任何一个角色x,并且x的下个奖池是y。如果再抽到一个角色z,他的下个奖池也是y。那么定义为神抽。让你求神抽的概率。结果取模。
思路:先统计一下每种值
i
i
i在角色池中出现的次数
c
n
t
i
cnt_i
cnti ,假设第一次抽
x
x
x池中的到
y
y
y ,那么
y
y
y对答案的贡献为: 抽到
x
x
x的概率
×
\times
×中
x
x
x抽到
y
y
y的概率
×
\times
×所有池子中抽
c
n
t
i
cnt_i
cnti的概率
**注意:**这里概率是分数,对模数取模比较特殊,比如分数 7 8 对 1 e 9 + 7 \frac{7}{8}对1e9+7 87对1e9+7取模。那么我们就要将 7 8 \frac{7}{8} 87看成 7 ∗ 1 8 7*\frac{1}{8} 7∗81的形式这里的 1 8 \frac{1}{8} 81也就是 8 − 1 8^{-1} 8−1。这里就要用乘法逆元去计算了。由于模数是一个素数。所以我们可以直接用快速幂和费尔马小定理求逆元。即 a − 1 m o d a^{-1}mod a−1mod p= a p − 2 m o d a^{p-2}mod ap−2mod p
代码:
//快速幂 a^b mod p
LL qmi(int a, int b, int p)
{
LL res = 1 % p;
while (b)
{
if (b & 1) res = res * a % p;
a = a * (LL)a % p;
b >>= 1;
}
return res;
}
void solve(){
int n;
cin>>n;
vector<int> f(1e6+10),cnt(1e6+10);
for(int i=0;i<n;i++){
int k;
cin>>k;
for(int j=0;j<k;j++){
int a;
cin>>a;
cnt[a]++;
f[a]=(f[a]+qmi(n,mod-2,mod)*qmi(k,mod-2,mod)%mod)%mod;
}
}
LL ans=0;
for(int i=1;i<=1e6;i++){
ans=(ans+f[i]*qmi(n,mod-2,mod)*cnt[i]%mod)%mod;
}
cout<<ans<<endl;
}