C++算法算法训练第十二天
C++算法算法训练第十二天
以下为牛客挑战
今日收获
知道了小根堆的写法
priority_queue<int,vector<int>,greater<int>>q;
用于小根堆,每次直接用top()取,得到里面最小的。
问图中有多少个连续的子集
0001100
我们只需要取判断,s[i]!=s[i+1]的个数就行了。我们可以看到一共有3个。
费马小定理求逆元。
ksm(2,mod-2,mod)---》2的-1次方。
组合数学
for(int i=2;i<=n;i++){
f[i]=f[i-1]*i%mod;//表示阶乘
g[i]=g[i-1]*ksm(i,mod-2,mod)%mod;//阶乘的倒数
}

牛客小白月赛128
模糊匹配

4
9
Apple0123
Apple0123
5
AKIOI
AK101
10
ilovezaoly
1loveza0Iy
6
banana
BANANA
YES
YES
NO
NO
解题代码
#include<bits/stdc++.h>
#define int long long
#define lll __uint128_t
#define PII pair<int ,int>
#define endl '\n'
using namespace std;
#define yn(ans) printf("%s\n", (ans)?"Yes":"No");//快速打印
#define YN(ans) printf("%s\n", (ans)?"YES":"NO");
#define REP(i, e) for (int i = 0; i < (e); ++i)
#define REP1(i, s, e) for (int i = (s); i <=(e); ++i)
#define TESTS int t; cin >> t; while (t--)
#define TEST
const int N=2e5+10,M=1e3+10,mod=1e9+7;
int a[N],b[N],c[N],pre[N];
void solve(){
int n;
cin>>n;
string s,s1;
cin>>s>>s1;
for(int i=0;i<n;i++){
if(s[i]=='O'){
s[i]='0';
}
if(s1[i]=='O'){
s1[i]='0';
}
if(s[i]=='I'||s[i]=='l'){
s[i]='1';
}
if(s1[i]=='I'||s1[i]=='l'){
s1[i]='1';
}
}
if(s==s1){
cout<<"YES"<<endl;
}else{
cout<<"NO"<<endl;
};
};
signed main(){
std::ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
TESTS{
solve();
};
return 0;
}
只留专一数

2
2
8 15
1
6
YES
NO
实际上我们通过观察,当选择一个数的时候
选两个不同的位置 i, j
令 a[i] = a[i] ^ a[j](a[i] 的 a[j] 次方)
令 a[j] = a[n'](用最后一个元素覆盖)
n' 减1(相当于数组长度-1,丢弃最后一个元素)
那么我们当到达最后一个的时候到底是什么一个情况
实际上最后会变成
a1^(a2*a3*a4*a5*a6*....ak)
指数部分是所有参与运算的其他数的乘积。
假设我们选 a[i] 作为最终的底数,其他所有数都作为指数的一部分:
- 最终
a[1] = a[i]^{(其他所有数的乘积)} - 指数部分不影响不同质因数的种类,只影响次数
- 所以只要
a[i]本身是专一数,最终结果也是专一数!
所以只要我们的数组中存在这个数,我们就可以得到专一数
具体解法
解题代码
#include<bits/stdc++.h>
#define int long long
#define lll __uint128_t
#define PII pair<int ,int>
#define endl '\n'
using namespace std;
#define yn(ans) printf("%s\n", (ans)?"Yes":"No");//快速打印
#define YN(ans) printf("%s\n", (ans)?"YES":"NO");
#define REP(i, e) for (int i = 0; i < (e); ++i)
#define REP1(i, s, e) for (int i = (s); i <=(e); ++i)
#define TESTS int t; cin >> t; while (t--)
#define TEST
const int N=2e5+10,M=1e3+10,mod=1e9+7;
int a[N],b[N],c[N],pre[N];
void solve(){
int n;
cin>>n;
vector<int>v(n+1);
for(int i=1;i<=n;i++){
cin>>v[i];
}
for(int i=1;i<=n;i++){
int flag=0;// 统计v[i]的不同质因数个数
for(int j=2;j*j<=v[i];j++){
if(v[i]%j)continue;// j不是因数,跳过
flag++;
while (v[i]%j==0)v[i]/=j;// 除尽这个质因数
}
if(v[i]>1)flag++;// 还剩一个大于1的质因数
// 如果a[i]本身是专一数(不同质因数个数<=1)
if(flag<=1){
cout<<"YES"<<endl;
return ;
}
}
cout<<"NO"<<endl;
};
signed main(){
std::ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
TESTS{
solve();
};
return 0;
}
牛客周赛 Round 129
小红的大小判断

3
right
解题代码
#include<bits/stdc++.h>
#define int long long
#define lll __uint128_t
#define PII pair<int ,int>
#define endl '\n'
using namespace std;
#define yn(ans) printf("%s\n", (ans)?"Yes":"No");//快速打印
#define YN(ans) printf("%s\n", (ans)?"YES":"NO");
#define REP(i, e) for (int i = 0; i < (e); ++i)
#define REP1(i, s, e) for (int i = (s); i <=(e); ++i)
#define TESTS int t; cin >> t; while (t--)
#define TEST
const int N=2e5+10,M=1e3+10,mod=1e9+7;
int a[N],b[N],c[N],pre[N];
signed main(){
std::ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int x;
cin>>x;
if(x>x*x){
cout<<"right";
}else{
cout<<"equal";
}
return 0;
}
小红的大小再判断
B-小红的大小再判断_牛客周赛 Round 129 (nowcoder.com)

示例1
abc
right
解题代码
#include<bits/stdc++.h>
#define int long long
#define lll __uint128_t
#define PII pair<int ,int>
#define endl '\n'
using namespace std;
#define yn(ans) printf("%s\n", (ans)?"Yes":"No");//快速打印
#define YN(ans) printf("%s\n", (ans)?"YES":"NO");
#define REP(i, e) for (int i = 0; i < (e); ++i)
#define REP1(i, s, e) for (int i = (s); i <=(e); ++i)
#define TESTS int t; cin >> t; while (t--)
#define TEST
const int N=2e5+10,M=1e3+10,mod=1e9+7;
int a[N],b[N],c[N],pre[N];
signed main(){
std::ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
string s,s1;
cin>>s;
s1=s;
reverse(s1.begin(),s1.end());
if(s>s1){
cout<<"left";
}else if(s==s1){
cout<<"equal";
}else{
cout<<"right";
}
return 0;
}
小红的肥鹅健身房
C-小红的肥鹅健身房_牛客周赛 Round 129 (nowcoder.com)

示例1
2 3 3
1 0 0
1 1 1
3 1
这个我们可以去考虑优先队列(小根堆),它可以帮我们每次取出的都是最小的,top();
取出最小的后和后一个开始比较,如果开始的后一个的相同就把这个数+1添加到小根堆中。然后一直取和pop
解题代码
#include<bits/stdc++.h>
#define int long long
#define lll __uint128_t
#define PII pair<int ,int>
#define endl '\n'
using namespace std;
#define yn(ans) printf("%s\n", (ans)?"Yes":"No");//快速打印
#define YN(ans) printf("%s\n", (ans)?"YES":"NO");
#define REP(i, e) for (int i = 0; i < (e); ++i)
#define REP1(i, s, e) for (int i = (s); i <=(e); ++i)
#define TESTS int t; cin >> t; while (t--)
#define TEST
const int N=2e5+10,M=1e3+10,mod=1e9+7;
int a[N],b[N],c[N],pre[N];
signed main(){
std::ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int n,m,k;
cin>>n>>m>>k;
priority_queue<int,vector<int>,greater<int>>q;
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
int x;
cin>>x;
if(x>0)q.push(x);
}
}
int ans=0,ans1=0;
while (q.size()>1){
int s=q.top();
q.pop();
if(s==q.top()){
q.pop();
q.push(s+1);
ans++;
if(s+1>=k){
ans1++;
}
}
}
cout<<ans<<" "<<ans1;
return 0;
}
小红的神秘密码解锁
D-小红的神秘密码解锁_牛客周赛 Round 129 (nowcoder.com)

示例1
011
2
颜色快我们可以这样去认为,连续相同数个数的类数。
0001100
我们只需要取判断,s[i]!=s[i+1]的个数就行了。我们可以看到一共有3个。
知道这个规律就行了
我们可以有这样的一种规律,我们取的区间的贡献只和开头和结尾有关

假设开始和前面的不一样那么就会得到减一的贡献,相同得到加一的贡献奖。
所以抵消的话后面的就要为相呼应的加上一和减去一就行了,所以我们只需要枚举这个字符串就行了,单枚举到减1的时候就去看看前面有多少个加一的。然后相反就看看有多少减1的。
最后要加上一个特殊的就是全部反转的
解题代码
#include<bits/stdc++.h>
#define int long long
#define lll __uint128_t
#define PII pair<int ,int>
#define endl '\n'
using namespace std;
#define yn(ans) printf("%s\n", (ans)?"Yes":"No");//快速打印
#define YN(ans) printf("%s\n", (ans)?"YES":"NO");
#define REP(i, e) for (int i = 0; i < (e); ++i)
#define REP1(i, s, e) for (int i = (s); i <=(e); ++i)
#define TESTS int t; cin >> t; while (t--)
#define TEST
const int N=2e5+10,M=1e3+10,mod=1e9+7;
int a[N],b[N],c[N],pre[N];
signed main(){
std::ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
string s;
cin>>s;
int same=0,nsame=0;
int ans=0;
for(int i=0;i+1<s.size();i++){
if(s[i]!=s[i+1]){
ans+=same;
nsame++;
}else{
ans+=nsame;
same++;
}
}
cout<<ans+1;
return 0;
}
小红的多维空间冒险
E-小红的多维空间冒险_牛客周赛 Round 129 (nowcoder.com)

3
12 12 4
这个题说的 根号k,我们就可以把外面包裹的去掉。
(x-y)的平方且x,y属于0和1只需要求两个的异或就行了
x^y--相同为0,不同为1,
所以对于k,我们只要选定k个位置为不同的,n-k为相同的,所以用排列组合
2的k次法表示k个位置每个位置都有两种不同的方式。n-k也一样。
但是最后要再除去2,我们没有规定u,v顺序,当时题目看到把这两种视为相同的一种。

从n中选k个。

解题代码
#include<bits/stdc++.h>
#define int long long
#define lll __uint128_t
#define PII pair<int ,int>
#define endl '\n'
using namespace std;
#define yn(ans) printf("%s\n", (ans)?"Yes":"No");//快速打印
#define YN(ans) printf("%s\n", (ans)?"YES":"NO");
#define REP(i, e) for (int i = 0; i < (e); ++i)
#define REP1(i, s, e) for (int i = (s); i <=(e); ++i)
#define TESTS int t; cin >> t; while (t--)
#define TEST
const int N=2e5+10,M=1e3+10,mod=1e9+7;
int a[N],b[N],c[N],pre[N];
int ksm(int p,int q,int mod){
int result=1;
p=p%mod;
while (q>0){
if(q&1){
result=(1ll*result*p)%mod;
}
q>>=1;
p=(1ll*p*p)%mod;
}
return result%mod;
}
signed main(){
std::ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int n;
cin>>n;
vector<int>f(n+1,1),g(n+1,1);
for(int i=2;i<=n;i++){
f[i]=f[i-1]*i;
g[i]=g[i-1]*ksm(i,mod-2,mod);
}
auto C=[&](int n,int k)->int{
if(n<k)return 0;
return f[n]*g[n-k]%mod*g[k]%mod;
};
for(int k=1;k<=n;k++){
int cur=C(n,k)*ksm(2,k,mod)%mod;
cur=(cur*ksm(2,n-k,mod)%mod);
cur=(cur* ksm(2,mod-2,mod))%mod;
cout<<cur<<" ";
}
return 0;
}
小红的魔法树探险
F-小红的魔法树探险_牛客周赛 Round 129 (nowcoder.com)

3
1 2
2 3
500000006
这个题就是我们可以去想想到底是每个点有子树和节点,我们选择那条路就是节点分之一的概率,我们可以去枚举1到所有顶点的期望,
期望==前面所有概率乘积x这个节点的深度。
dfs遍历
解题代码
#include<bits/stdc++.h>
#define int long long
#define lll __uint128_t
#define PII pair<int ,int>
#define endl '\n'
using namespace std;
#define yn(ans) printf("%s\n", (ans)?"Yes":"No");//快速打印
#define YN(ans) printf("%s\n", (ans)?"YES":"NO");
#define REP(i, e) for (int i = 0; i < (e); ++i)
#define REP1(i, s, e) for (int i = (s); i <=(e); ++i)
#define TESTS int t; cin >> t; while (t--)
#define TEST
const int N=2e5+10,M=1e3+10,mod=1e9+7;
int a[N],b[N],c[N],pre[N];
int ksm(int p,int q,int mod){
int result=1;
p=p%mod;
while (q>0){
if(q&1){
result=(1ll*result*p)%mod;
}
q>>=1;
p=(1ll*p*p)%mod;
}
return result%mod;
}
signed main(){
std::ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int n;
cin>>n;
vector<vector<int>>g(n+1);
for(int i=0;i<n-1;i++){
int u,v;
cin>>u>>v;
g[u].push_back(v);
g[v].push_back(u);
}
int ans=0;
auto dfs=[&](auto &&self,int u,int fa,int s,int dep)->void{
s*=ksm(g[u].size(),mod-2,mod);
s%=mod;
if(u>1){
ans+=s*dep%mod;
ans%=mod;
}
for(auto &v:g[u]){
if(v==fa)continue;
self(self,v,u,s,dep+1);
}
s*=g[u].size();//回溯
s%=mod;
};
dfs(dfs,1,0,1,1);
cout<<ans<<endl;
return 0;
}

浙公网安备 33010602011771号