CF 667 Div3

A.数数

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+5;
const ll mod=1e9+7;
 
int main(){
    int t;
    cin>>t;
    while(t--){
        int n;
        cin>>n;
        int x=n%10;
        int s=10;
        int sum=0;
        for(int i=1;i<x;i++)sum+=10;
        if(n/10==0)sum+=1;
        else if(n/100==0)sum+=3;
        else if(n/1000==0)sum+=6;
        else sum+=10;
        cout<<sum<<endl;
    }
    return 0;    
} 
View Code

B.1之间0的个数

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+5;
const ll mod=1e9+7;
int minn=100000;
int n;
int a[N];
 
int main(){
    int t;
    cin>>t;
    while(t--){
        scanf("%d",&n);
        int sum=0;
        int l=-1;
        for(int i=1;i<=n;i++){
        scanf("%d",&a[i]);    
        if(a[i]==1)
        if(l==-1)l=i;
        else sum+=i-l-1,l=i;
        }
        
        cout<<sum<<endl;
    }
    return 0;    
} 
View Code

C.找出最大值并且两边至少有一个小于它的点,这样他就可以进化了成为新的最大。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=4e5+5;
const ll mod=1e9+7;
int minn=100000;
int n;
int a[N];
int main(){
    int t;
    cin>>t;
    while(t--){
        int n;scanf("%d",&n);
        int f=0;
        int z=0;
        int maxn=-1;
        for(int i=1;i<=n;i++){
            scanf("%d",&a[i]);
            if(a[i]>maxn)maxn=a[i];
            if(i!=1&&a[i]!=a[i-1])f=1;
        }
        for(int i=1;i<=n;i++){
            if(z)break;
            if(a[i]==maxn){
                if(i-1>=1&&a[i-1]!=maxn)
                z=i;
                if(i+1<=n&&a[i+1]!=maxn)
                z=i;
            }
        }
        if(!f)cout<<-1<<endl;
        else cout<<z<<endl;
    }
    return 0;    
} 
 
View Code

D.构造一个图,首先我们选不同的两个点相连,这样再将其余的点连到这两个点之一上。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=4e5+5;
const ll mod=1e9+7;
int minn=100000;
int n;
int a[N];
int main(){
    int t;
    cin>>t;
    while(t--){
        int n;scanf("%d",&n);
        int f=0;
        int l,r;
        for(int i=1;i<=n;i++){
            scanf("%d",&a[i]);
            if(i!=1&&a[i]!=a[i-1]){
                l=i-1;
                r=i;
                f=1;
            }
        }
        if(!f)printf("NO
");
        else{
            printf("YES
");
            printf("%d %d
",l,r);
            for(int i=1;i<=n;i++){
                if(i==l||i==r)continue;
                if(a[i]!=a[l]){
                    printf("%d %d
",i,l);
                }else{
                    printf("%d %d
",i,r);
                }
            }
        }
    }
    return 0;    
} 
View Code

E.n个人,分人数相同的两组成环的方案数。

1:n人成环的方案数为 (n-1)!

因此先分两份且不重复,C(N,N/2)/2

再乘以两边的环排列 

最终为C(N,N/2)/2*(N/2-1)!*(N/2-1)!

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=4e5+5;
const ll mod=1e9+7;
int minn=100000;
int n;
ll a[N];
void init(){
    a[0]=1;
    for(int i=1;i<=20;i++)a[i]=a[i-1]*i;
}
ll c(ll m){
    return a[m]/a[(m/2)]/a[(m/2)];
}
int main(){
    init();
    int t;
    ll n;
    cin>>n;
    if(n==2){
        cout<<1<<endl;
        return 0;
    }else{
        ll l=n/2;
        ll sum=1;
        sum*=c(n)/2;
        sum*=a[(n/2)-1];
        sum*=a[(n/2)-1];
        cout<<sum<<endl;
    }
    return 0;    
} 
View Code

F.DP bitset 优化,但是有更好的方法,我写的烂,别学

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=300000;
const ll mod=1e9+7;
bitset<N> st;
int g[N];
int a[100][100];
int main(){
    int n,m,k;
    scanf("%d%d%d",&n,&m,&k);
    int i,j;
    int maxn=0;
    st[0]=1;
    for(i=1;i<=n;i++){
        for(j=1;j<=m;j++){
            scanf("%d",&a[i][j]);
            for(int k=maxn+a[i][j];k>=a[i][j];k--){
            int op=k-a[i][j];
                if(st[k]){
                    if(st[op])
                    g[k]=min(g[op]+1,g[k]);
                }else{
                    if(st[op]){
                    if(g[op]<m/2){
                    g[k]=g[op]+1;
                    st[k]=1;
                    maxn=max(maxn,k);
                    }
                    }
                }
                
            }
        }
        memset(g,0,sizeof g);
    }
    for(i=(maxn+160)/k*k;i>=0;i-=k){
        if(st[i]){
            printf("%d
",i);
            return 0;
        }
    }
    return 0;    
} 
View Code

G.让一条边为0,给的点对的最短路的总和最小

先算出所有点对的最短路

枚举每一条边,为0,在判断大小 

1:经过该点

2:不过

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<ll,ll> p;
const int N=1001;
const int M=100005;
int n,m,k;
int head[N];
ll s[N][N];
ll dis[N];
int vis[N];
struct edge{
    int from,to,ne,dis;
}e[M];
int cnt;
void add(int x,int y,int w){
    e[cnt].from=x,e[cnt].to=y,e[cnt].dis=w,e[cnt].ne=head[x],head[x]=cnt++;
}
void dij(int b){
    int begin=b;
    memset(dis,0x3f,sizeof dis);
    memset(vis,0,sizeof vis);
    dis[b]=0;
    priority_queue<p,vector<p> ,greater<p> >st;
    st.push({0,begin});
    while(!st.empty()){
        p x=st.top();
        st.pop();
        int v=x.second;
        if(vis[v])continue;
        vis[v]=1;
        for(int i=head[v];~i;i=e[i].ne){
            int j=e[i].to,w=e[i].dis;
            if(dis[j]>dis[v]+w){
                dis[j]=dis[v]+w;
                st.push({dis[j],j});
            }
        }
    }
    for(int i=1;i<=n;i++)s[b][i]=dis[i];
}
vector<p> sk;
int main(){
    memset(head,-1,sizeof head);
    
    scanf("%d%d%d",&n,&m,&k);
    for(int i=1;i<=m;i++){
        int x,y,w;scanf("%d%d%d",&x,&y,&w);
        add(x,y,w);add(y,x,w);
    }
    for(int i=1;i<=k;i++){
        ll x,y;scanf("%lld%lld",&x,&y);
        sk.push_back({x,y});
    }
    ll minn=1e18;
    
    for(int i=1;i<=n;i++)dij(i);
    for(int i=0;i<2*m;i+=2){
        ll sum=0;
        int x=e[i].from,y=e[i].to;
        for(int j=0;j<k;j++){
            int f=sk[j].first,tt=sk[j].second;
            sum+=min(s[f][tt],min(s[f][x]+s[y][tt],s[f][y]+s[x][tt]));
        }
        minn=min(minn,sum);
    }
    cout<<minn<<endl;
}
View Code
原文地址:https://www.cnblogs.com/Ean1zhi/p/13861836.html