Zut_round 1 (CF #479 DIV3)

A:给一个数n操作k次,对于每次:如果n%10==0,n/=10,否则n--。

模拟

#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define pai acos(-1)
const LL  mod = 1000000007;
const int MXN = 5e5+5;

int main(){
    int n,k;scanf("%d%d",&n,&k);
    while(k--){
        if(n%10==0)n/=10;
        else n--;
    }
    printf("%d",n);
    return 0;
}

B:给一个字符串,求出现最多的2元串

直接map,key为二元串,value为出现次数。

#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define pai acos(-1)
const LL  mod = 1000000007;
const int MXN = 5e5+5;
map<string,int>m;
map<string,int>::iterator it;
int main(){
    int n;string s;cin>>n>>s;
    for(int i=0;i<n-1;i++){
        string t;t=t+s[i];t=t+s[i+1];m[t]++;
    }
    int ans=0;string u;
    for(auto it:m){
       if(ans<(it.second)){ans=it.second;u=it.first;}
    }
    cout<<u;
    return 0;
}

C:给一个数组,求是否一个x,x在【1,1e9】内,并且恰好有k个元素小于等于x。

注意判断k==0以及k==n,然后对于其他的数,sort后判断a[k]!=a[k+1]是否成立即可。输出的时候输出a[k]即可。

#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define pai acos(-1)
const LL  mod = 1000000007;
const int MXN = 2e5+5;
int a[MXN]={1};
int main(){
    int n,k;cin>>n>>k;for(int i=1;i<=n;i++)scanf("%d",&a[i]);
    sort(a+1,a+1+n);
    if(k==n)printf("%d",a[k]);
    else if(a[k]==a[k+1])printf("-1");
    else printf("%d",a[k]);
    return 0;
}

D:先给定一个数n,对于n可以有两种操作,n*=2,n/=3(n能整除3),操作n-1次得到n个数,打乱顺序后,让还原。

解法1:dfs裸题,满足要求就dfs下去即可,因为每次满足的不会有很多,甚至没有,所以dfs树分枝会很少。

解法2:先找出第一个数(3最多,2最少),然后找可以变成的数即可。

#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define pai acos(-1)
const LL  mod = 1000000007;
const int MXN = 2e5+5;
LL n,a[105];
LL path[105];bool vis[105],is_found;
void dfs(int ro){
    if(is_found)return;
    if(ro==n+1){is_found=1;return;}
    for(int i=1;i<=n;i++){
        if(is_found)break;
        if(vis[i])continue;
        if(ro==1||(path[ro-1]%a[i]==0LL&&path[ro-1]/a[i]==3LL)||(a[i]%path[ro-1]==0&&a[i]/path[ro-1]==2LL)){
            vis[i]=1;path[ro]=a[i];
            dfs(ro+1);
            vis[i]=0;
        }
    }
}
int main(){
    scanf("%lld",&n);for(int i=1;i<=n;i++)scanf("%lld",&a[i]);
    dfs(1);
    for(int i=1;i<=n;i++)printf("%lld ",path[i]);
    return 0;
}
#include<bits/stdc++.h>
using namespace std;
#define int long long //!
#define pai acos(-1)
//const LL  mod = 1000000007;
const int MXN = 2e5+5;
int a[105];bool vis[105];
vector<int>v;
int f(int x,int c){
    int p=0;while(x%c==0){p++;x/=c;}return p;
}
signed main(){ //!
    int n;scanf("%lld",&n);for(int i=1;i<=n;i++)scanf("%lld",&a[i]);
    int mi=INT_MAX,u;
    for(int i=1;i<=n;i++){
        int cnt=f(a[i],2);
        if(cnt<mi){mi=cnt,u=i;}
    }
    for(int i=1;i<=n;i++){
        int cnt=f(a[i],2);
        if(cnt==mi)
            v.push_back(i);
    }
    int mx=-1;
    for(auto i:v){
        int cnt=f(a[i],3);
        if(cnt>mx){mx=cnt,u=i;}
    }
    cout<<a[u];vis[u]=1;int last=a[u];
    for(int z=2;z<=n;z++){
        for(int i=1;i<=n;i++){
            if(vis[i])continue;
            if(a[i]%last==0&&a[i]/last==2){
                printf(" %lld",a[i]);vis[i]=1;last=a[i];
            }
            if(last%a[i]==0&&last/a[i]==3){
                printf(" %lld",a[i]);vis[i]=1;last=a[i];
            }
        }
    }
    return 0;
}

 

 

E:求一张图里有几个单纯环(即一个联通块只能是一个环,不能有别的多余边

用并查集维护,对于属于一个联通块的,判断度是否为2即可。

#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define pai acos(-1)
const LL  mod = 1000000007;
const int MXN = 2e5+5;
int fa[MXN],du[MXN];
int found(int x){
    if(fa[x]==x)return x;
    return fa[x]=found(fa[x]);
}
vector<int>v[MXN];
int main(){
    int n,m;scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)fa[i]=i;
    for(int i=1;i<=m;i++){
        int u,v;scanf("%d%d",&u,&v);
        du[u]++,du[v]++;
        int fu,fv;fu=found(u);fv=found(v);
        if(fu!=fv) fa[fu]=fv;
    }
    for(int i=1;i<=n;i++){
        v[found(i)].push_back(i);
    }int ans=0;
    for(int i=1;i<=n;i++){
        if(v[i].size()<=2)continue;
        int tag=1;
        for(auto it:v[i]){
            if(du[it]!=2){tag=0;break;}
        }
        if(tag) ans++;
    }
    printf("%d",ans);
    return 0;
}

F:给一个数组,求lcs,但是相邻两项差1。

my解法1:dp,用前i位更新第i位,set存第i位之前的信息,对于第i位,在set找满足题意的节点,然后更新dp,用链表存储前躯。

解法2:mp离散化,(mp真好使

#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define pai acos(-1)
const LL  mod = 1000000007;
const int MXN = 2e5+5;
struct no{int u,val,dd;};
bool operator<(const no &x,const no &y){
    if(x.val==y.val)return x.dd<y.dd;
    return x.val<y.val;
}
int a[MXN];
int dp[MXN],pre[MXN];
multiset<no>s;multiset<no>::iterator it;
vector<int>ans;
int main(){
    int n;scanf("%d",&n);for(int i=1;i<=n;i++)scanf("%d",&a[i]);
    dp[1]=1,pre[1]=-1;s.insert(no{1,a[1],1});
    for(int i=2;i<=n;i++){
        no now=no{i,a[i]-1,INT_MAX};
        it=s.upper_bound(now);
        if(it==s.begin()){
            dp[i]=1;pre[i]=-1;s.insert(no{i,a[i],dp[i]});
            continue;
        }
        it--;
        if(it->val!=a[i]-1){
            dp[i]=1;pre[i]=-1;s.insert(no{i,a[i],dp[i]});
            continue;
        }
        dp[i]=it->dd+1;pre[i]=it->u;
        s.insert(no{i,a[i],dp[i]});
    }
    int mx=0,u;
    for(int i=1;i<=n;i++){
        if(dp[i]>mx){mx=dp[i],u=i;}
    }
    printf("%d\n",mx);
    for(int i=u;i!=-1;i=pre[i])ans.push_back(i);
    for(int i=ans.size()-1;i>=0;i--)printf("%d ",ans[i]);
    return 0;
}
#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define pai acos(-1)
const LL  mod = 1000000007;
const int MXN = 2e5+5;
int a[MXN];
map<int,int>dp;
int main(){
    int n;scanf("%d",&n);for(int i=1;i<=n;i++)scanf("%d",&a[i]);
    for(int i=1;i<=n;i++)dp[a[i]]=dp[a[i]-1]+1;
    int mx=0,ed;
    for(auto it:dp){
        if(it.second>mx){mx=it.second;ed=it.first;}
    }
    int st=ed-mx+1;
    printf("%d\n",mx);
    for(int i=1;i<=n;i++){
        if(a[i]==st){printf("%d ",i);st++;}
    }
    return 0;
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值