题目链接:https://ac.nowcoder.com/acm/contest/392#question

A

这个贪心 我觉得蛮难写的(主要是我太菜了

我们先将所有区间按照左端点排序,然后从左往右遍历。

用一个变量比如e来代表我们当前最远可以够到的右端点

然后内层循环每次枚举 左端点 不超过 右端点+1 的所有区间

然后从其中选择一个右端点最靠右的,更新e的值即可。

(注意两个小细节:1、内层贪心的时候 要限定 j<m  不然会数组越界  2、内层贪心的时候要记录下结束的位置  贪心结束后在外层要直接跳过去

时间复杂度O(NlogN)

#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<string.h>
#include<math.h>
using namespace std;
const int maxn=1e5+7;
typedef long long ll;
typedef struct node{
    int l,r;
}node;
node a[maxn];
int n,m;
bool cmp(node a,node b){
    return a.l<b.l;
}
int main(){
    scanf("%d%d",&n,&m);
    for(int i=0;i<m;i++){
        scanf("%d%d",&a[i].l,&a[i].r);
    }
    sort(a,a+m,cmp);
    if(a[0].l!=1){printf("-1\n");return 0;}

    int e=0,cnt=0;
    for(int i=0;i<m;i++){

        int mx=e,d=0;
        for(int j=i;a[j].l<=e+1&&j<m;j++){//注意j的范围
            mx=max(a[j].r,mx);
            d=j;//记录结束位置
        }
        if(mx>e){
            e=mx;cnt++;i=d;
            if(e>=n)break;
        }
        else break;//找不到能选择的点
    }
    if(e<n)cnt=-1;
    printf("%d\n",cnt);
    return 0;
}

B

快速幂+快速乘

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll x,n,mod;
ll mul(ll a,ll b){
	a%=mod;
	b%=mod;
	ll c=(long double)a*b/mod;
	ll ans=a*b-c*mod;
	return (ans%mod+mod)%mod;
}
ll pow_mod(ll x,ll n){
	ll res=1;
	while(n){
		if(n&1)
		res=mul(res,x);
		x=mul(x,x);
		n>>=1;
	}
	return res;
}
int T;
int main(){
    scanf("%d",&T);

	while(T--){
        cin>>x>>n>>mod;
        cout<<pow_mod(x,n)<<endl;
	}

}

C

 

D

E

二分答案的标准模板

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e6+7;
int a[maxn];
int n,m;
int check(int mid){
    int sum=0;
    for(int i=0;i<n;i++)sum+=a[i]/mid;

    if(sum>=m)return true;
    else return false;
}
int main(){
    scanf("%d%d",&n,&m);
    int mx=0;
    for(int i=0;i<n;i++){
        scanf("%d",&a[i]);
        mx=a[i]>mx?a[i]:mx;
    }
    int l=1,r=mx,ans=0;
    while(l<=r){
        int mid=(l+r)/2;
        if(check(mid))l=mid+1,ans=mid;
        else r=mid-1;
    }
    printf("%d\n",ans);
    return 0;
}

F

G

贴下赛后题解

(比赛的时候猜的

#include<stdio.h>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
int gcd(ll a,ll b){
	ll r;
	while(b>0){
		r=b;
		b=a%b;
		a=r;
	}
	return a;
}
int main(){
	ll a,b;
    string s;
	cin>>a>>b>>s;
	cout<<gcd(a,b);
}

H

I

说是tarjan算法入门

可是我不会

赛后学了两个小时 勉强学明白有向图tarjan算法咋写   但是这个题是无向图  

勉强对着别人的代码  改对了 但是还不太懂   随后要补补

#include<string.h>
#include<iostream>
#include<algorithm>
#include<stdio.h>
#include<math.h>
#include<vector>
using namespace std;

const int maxn=1e5+7;
vector<int>a[maxn];
int dfn[maxn],low[maxn];
int top,deep,ans;
void tarjan(int u,int fa){
    dfn[u]=++deep;
    low[u]=deep;

    for(int i=0;i<a[u].size();i++){
        int v=a[u][i];
        if(v==fa)continue;
        if(!dfn[v]){
            tarjan(v,u);
            low[u]=min(low[u],low[v]);
            if(low[v]>dfn[u])ans++;
        }
        else{
            low[u]=min(low[u],dfn[v]);
        }
    }
    return ;
}

int main(){
    int n,m,u,v;
    scanf("%d%d",&n,&m);
    for(int i=0;i<m;i++){
        scanf("%d%d",&u,&v);
        a[u].push_back(v);
        a[v].push_back(u);
    }
    tarjan(1,0);

    printf("%d\n",m-ans);
    return 0;
}

J