zoukankan      html  css  js  c++  java
  • 2020牛客寒假算法基础集训营1 J题可以回顾回顾

    2020牛客寒假算法基础集训营1

    这套题整体来说还是很简单的。

    A.honoka和格点三角形

    这个题目不是很难,不过要考虑周全,面积是1,那么底边的长度可以是1也可以是2,

    注意底边1和2会有重复的,所以要注意去除这个重复部分的。

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=2e5+10;
    typedef long long ll;
    const int mod=1e9+7;
    int main(){
        ll n,m,ans=0;
        scanf("%lld%lld",&n,&m);
        ans=2*(m-2)%mod*m%mod*(n-1)%mod;
        ans+=2*(n-2)%mod*n%mod*(m-1)%mod;
        ans+=2*(m-1)%mod*(m-2)%mod*(n-2)%mod;
        ans+=2*(n-1)%mod*(n-2)%mod*(m-2)%mod;
        ans%=mod;
        printf("%lld
    ",ans);
        return 0;
    }
    A

    B.kotori和bangdream

    这个题目也很简单,因为每一个音符的概率都是确定的。。

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=2e5+10;
    typedef long long ll;
     
    int main(){
        int n,x,a,b;
        cin>>n>>x>>a>>b;
        double ans=n*x*a+n*(100-x)*b;
        ans/=100.0;
        printf("%.2f
    ",ans);
        return 0;
    }
    B

    C.umi和弓道

    这个可能看起来稍微复杂一点,不过整体还是很简单,

    把所有可以投影到y轴的投影到y轴,可以投影到x轴的投影到x轴。

    然后排个序,求长度最短的n-k个点。

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=3e5+10;
    typedef long long ll;
    long double dx[maxn],dy[maxn];
    long double x[maxn],y[maxn];
    int judge(ll x,ll y){
        if(x>0&&y>0) return 1;
        if(x<0&&y>0) return 2;
        if(x<0&&y<0) return 3;
        if(x>0&&y<0) return 4;
    }
    int main(){
        ll n,k;
        long double x0,y0;
        scanf("%Lf%Lf%lld%lld",&x0,&y0,&n,&k);
        int f=judge(x0,y0);
        int num=0,numx=0,numy=0;
        for(int i=1;i<=n;i++){
            scanf("%Lf%Lf",&x[i],&y[i]);
            int ans=judge(x[i],y[i]);
            if(ans==f) num++;
            else if(x0*x[i]>0) numx++;
            else if(y0*y[i]>0) numy++;
        }
        if(num+numx>k&&num+numy>k){
            printf("-1
    ");
            return 0;
        }
        int cntx=0,cnty=0;
        for(int i=1;i<=n;i++){
            if(x[i]*x0<0){
    //            cout<<"i="<<i<<" x[i]="<<x[i]<<" y[i]="<<y[i]<<endl;
                dy[++cnty]=(y0-y[i])/(x0-x[i])*(-x0)+y0;
    //            printf("dy[%d]=%Lf
    ",cnty,dy[cnty]);
            }
            if(y0*y[i]<0){
                dx[++cntx]=(x0-x[i])/(y0-y[i])*(-y0)+x0;
            }
        }
        int res=n-k;
        sort(dy+1,dy+1+cnty);
        sort(dx+1,dx+1+cntx);
        long double ans=2e9;
        for(int i=res;i<=cntx;i++){
    //        printf("dx[%d]=%Lf
    ",i,dx[i]);
            ans=min(ans,dx[i]-dx[i-res+1]);
        }
        for(int i=res;i<=cnty;i++){
    //        printf("dy[%d]=%Lf dy[%d]=%Lf
    ",i,dy[i],i-res+1,dy[i-res+1]);
            ans=min(ans,dy[i]-dy[i-res+1]);
        }
        printf("%.6Lf
    ",ans);
        return 0;
    }
    C

    D.hanayo和米饭

    这个太签到了

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=2e5+10;
    typedef long long ll;
     
    int vis[maxn];
     
    int main(){
        int n;
        scanf("%d",&n);
        for(int i=1;i<n;i++){
            int x;
            scanf("%d",&x);
            vis[x]=1;
        }
        for(int i=1;i<=n;i++){
            if(!vis[i]){
                printf("%d
    ",i);
                return 0;
            }
        }
    }
    D

    E.rin和快速迭代

     这个题目f函数其实求的就是约数的个数,这个还是很好求的,

    把这个数唯一分解,x=p1^a1*p2^a2*....*pn^an

    那么这个数的约数的个数就是 num=(a1+1)*(a2+1)*...*(an+1)

    这个就暴力求就可以了。

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=1e6+10;
    typedef long long ll;
    const int mod=1e9+7;
    ll v[maxn],isp[maxn],m;
    void init1()
    {
        for(int i=2;i<maxn;i++){
            if(v[i]==0){
                isp[m++]=i;
                v[i]=i;
            }
            for(int j=0;j<m;j++){
                if(v[i]<isp[j]||i*isp[j]>maxn) break;
                v[i*isp[j]]=isp[j];
            }
        }
    }
    ll judge(ll x){
        ll ans=1,p=1;
        for(int i=0;i<m;i++){
            while(x%isp[i]==0){
    //            printf("isp[%d]=%d
    ",i,isp[i]);
                p++,x/=isp[i];
            }
            ans*=p,p=1;
            if(x==1) break;
        } 
        if(x>1) ans*=2;
    //    printf("x=%lld ans=%lld
    ",x,ans);
        return ans;
    }
    
    int main(){
        init1();
        ll n,res=0;
        scanf("%lld",&n);
        while(n>2) n=judge(n),res++;
        printf("%lld
    ",res);
        return 0;
    }
    E

    F.maki和tree

    这个题目我觉得我写的挺复杂的,

    我是先预处理出白色块的连通块。

    然后对于每一个黑块去枚举它周围的白色连通块。

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=2e5+10;
    typedef long long ll;
    struct node{
        int v,nxt;
        node(int v=0,int nxt=0):v(v),nxt(nxt){}
    }e[maxn*2];
    int head[maxn],cnt;
    void add(int u,int v){
        e[++cnt]=node(v,head[u]);
        head[u]=cnt;
        e[++cnt]=node(u,head[v]);
        head[v]=cnt;
    }
    int f[maxn],sum[maxn];
    char s[maxn];
    void dfs(int u,int pre){
        f[u]=pre,sum[u]=1;
        for(int i=head[u];i;i=e[i].nxt){
            int v=e[i].v;
            if(v==pre) continue;
            dfs(v,u);
            if(s[u]!='B'&&s[v]!='B') sum[u]+=sum[v];
        }
    }
    void dfs1(int u,int pre){
        for(int i=head[u];i;i=e[i].nxt){
            int v=e[i].v;
            if(v==pre) continue;
            if(s[u]!='B'&&s[v]!='B') sum[v]=max(sum[v],sum[u]);
            dfs1(v,u);
        }
    }
    ll ans=0;
    void dfsans(int u,int pre){
        for(int i=head[u];i;i=e[i].nxt){
            int v=e[i].v;
            if(v==pre) continue;
            dfsans(v,u);
        }
        if(s[u]!='B') return ;
        ll all=1;
        for(int i=head[u];i;i=e[i].nxt){
            int v=e[i].v;
            if(s[v]=='B') continue;
            all+=sum[v];
            ans-=sum[v]*(sum[v]-1)/2;
        }
        ans+=all*(all-1)/2;
    }
    int main(){
        int n;
        scanf("%d%s",&n,s+1);
        for(int i=1;i<n;i++){
            int u,v;
            scanf("%d%d",&u,&v);
            add(u,v);
        }
        dfs(1,-1),dfs1(1,-1);
        dfsans(1,-1);
        printf("%lld
    ",ans);
    }
    F

    G.eli和字符串

    这个题目很简单,直接暴力枚举26个字母即可。

    #include<bits/stdc++.h>
    #define inf 0x3f3f3f3f
    using namespace std;
    const int maxn=2e5+10;
    typedef long long ll;
    char s[maxn];
    int num[30],pos[30][maxn];
    int main(){
        int n,k;
        scanf("%d%d%s",&n,&k,s+1);
        int slen=strlen(s+1);
        for(int i=1;i<=slen;i++){
            int x=s[i]-'a';
            num[x]++;
            pos[x][num[x]]=i;
        }
        int ans=inf;
        for(int i=0;i<26;i++){
            if(num[i]<k) continue;
            int cnt=0;
            for(int j=k;j<=num[i];j++) ans=min(ans,pos[i][j]-pos[i][j-k+1]+1);
        }
        if(ans>=inf) ans=-1;
        printf("%d
    ",ans);
        return 0;
    }
    G

    H.nozomi和字符串

    这个是一个二分,二分最大长度即可。

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=2e5+10;
    typedef long long ll;
    const int mod=1e9+7;
    char s[maxn];
    int n,k,slen;
    int num[2][maxn];
    bool check(int x){
        for(int i=x;i<=slen;i++){
            int len0=num[0][i]-num[0][i-x];
            int len1=num[1][i]-num[1][i-x];
            if(len0<=k||len1<=k) return true;
        }
        return false;
    }
    int main(){
        scanf("%d%d%s",&n,&k,s+1);
        slen=strlen(s+1);
        for(int i=1;i<=slen;i++){
            num[0][i]=num[0][i-1];
            num[1][i]=num[1][i-1];
            num[s[i]-'0'][i]++;
        }
        int l=0,r=n,ans=0;
        while(l<=r){
            int mid=(l+r)>>1;
            if(check(mid)) ans=mid,l=mid+1;
            else r=mid-1;
        }
        printf("%d
    ",ans);
        return 0;
    }
    H

    I.nico和niconiconi

    这个是一个dp,注意细节的处理。

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=3e5+10;
    typedef long long ll;
    char cur[]={'n','i','c','o'},s[maxn];
    ll dp[maxn];
    int main(){
        ll n,a,b,c;
        scanf("%lld%lld%lld%lld%s",&n,&a,&b,&c,s+1);
        for(int i=1;i<=n;i++){
            dp[i]=max(dp[i-1]+a,dp[i]);
            if(i>=2) dp[i]=max(dp[i],dp[i-2]+b);
            if(i>=3) dp[i]=max(dp[i],dp[i-3]+c);
        }
        ll ans=0;
        int num=0,pos=0,slen=strlen(s+1);
        s[++slen]='~';
        for(int i=1;i<=slen;i++){
            if(s[i]==cur[pos]) {
                pos++;
                if(pos==4) num++,pos=0;
            }
            else{
                ll res=dp[num];
                if(pos>=2){
                    if(num>=1) res=max(dp[num-1]+b,res);
                    if(num>=2) res=max(dp[num-2]+c,res);
                }
                ans+=res,num=0,pos=0;
                if(s[i]==cur[pos]) pos++;
            }
        }
        printf("%lld
    ",ans);
        return 0;
    }
    /*
    19 1 2 5
    niconiconiniconico
    */
    I

    J.u's的影响力

    这个推一下就会发现,x和y的指数都是斐波那契数列的一项,a^b的指数是斐波那契数列的前缀和。

    所以都可以用矩阵快速幂解决,斐波那契数列前缀和也可以用矩阵快速幂解决。

    推荐资料:大斐波拉契数列及斐波拉契前缀和(m阶前缀和)求解

    斐波那契数列总(这个挺好的)

    但是这个还有几个点需要注意,第一个:斐波那契数列求的是指数,所以不可以直接对mod取模,而是要对mod-1取模,因为费马小定理。

    ap-1 mod p == 1 所以只可以对p-1取模。

    第二个就是a是p的倍数时,不满足费马小定理,这个要分开考虑。

    #include <iostream>
    #include <algorithm>
    #include <cstdio>
    #include <cstring>
    using namespace std;
    typedef long long ll;
    const long long mod = 1e9+7;
    
    int UP;
    struct mat
    {
        long long mn[10][10];
        mat() {
            for(int i = 0;i<UP;i++) {
                for(int j = 0;j<UP;j++) {
                    mn[i][j]=0;
                }
            }
            for(int i = 0;i<UP;i++) {
                mn[i][i] = 1;
            }
        }
        void init(){
            for(int i=0;i<UP;i++){
                for(int j=0;j<UP;j++){
                    mn[i][j]=0;
                }
            }
        }
       mat operator * (const mat& a) {
            mat res;
            for(int i = 0;i<UP;i++) {
                res.mn[i][i] = 0;
            }
            for(int i=0;i<UP;i++) {
                for(int j=0;j<UP;j++) {
                    for(int k=0;k<UP;k++) {
                        res.mn[i][j] += mn[i][k]*a.mn[k][j]%(mod-1);
                        res.mn[i][j] %= (mod-1);
                    }
                }
            }
            return res;
        }
    };
    
    mat fast(mat a,long long c) {
        mat res = mat();
        while(c) {
            if(c&1) res  = res * a;
            a = a*a;
            c >>= 1;
        }
        return res;
    }
    ll quick_mul(ll a,ll b,ll mod)
    {
        ll ans = 0;
        while(b)
        {
            if (b & 1) ans = (ans + a) % mod;
            a = (a + a) % mod;
            b >>= 1;
        }
        return ans;
    }
    
    ll quick_pow(ll a,ll b,ll mod)
    {
        ll ans = 1;
        while(b)
        {
            if (b & 1) ans = quick_mul(ans, a, mod);
            a = quick_mul(a, a, mod);
            b >>= 1;
        }
        return ans;
    }
    int main(){
        UP=2;
        ll n,x,y,a,b;
        scanf("%lld%lld%lld%lld%lld",&n,&x,&y,&a,&b);
        if(n==1) {
            printf("%lld
    ",x%mod);
            return 0;
        }
        if(n==2){
            printf("%lld
    ",y%mod);
            return 0;
        }
        if(x%mod==0||y%mod==0||a%mod==0){
            printf("0
    ");
            return 0;
        }
        mat res;res.init();
        res.mn[1][1]=0,res.mn[0][0]=res.mn[0][1]=res.mn[1][0]=1;
        res=fast(res,n-2);
        x=quick_pow(x,res.mn[1][0],mod);
        y=quick_pow(y,res.mn[0][0],mod);
        a%=mod,a=quick_pow(a,b,mod);
        UP=3,res.init();
        res.mn[0][1]=res.mn[1][0]=res.mn[1][1]=1;
        res.mn[2][0]=res.mn[2][1]=res.mn[2][2]=1;
        res=fast(res,n-3);
        a=quick_pow(a,res.mn[2][1]+res.mn[2][2],mod);
        printf("%lld
    ",quick_mul(quick_mul(a,x,mod),y,mod));
        return 0;
    }
    J
  • 相关阅读:
    .net中使用事务 dodo
    dnn中NULL值的处理 dodo
    通过sql server的作业调度+存储过程来实现系统定时任务的方法 dodo
    使用With...End With dodo
    ASP.NET页面中使用SolpartMenu控件 dodo
    浅解web打印 dodo
    WEB打印大全(转) dodo
    AjaxMethod未定义原因 dodo
    CommandEventArgs.CommandArgument 属性 dodo
    在用VS.NET2003 新建项目时系统提示 autometion服务器无法创建对象 这是什么问题? dodo
  • 原文地址:https://www.cnblogs.com/EchoZQN/p/12272902.html
Copyright © 2011-2022 走看看