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

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

    A.做游戏

    这是个签到题。

    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <queue>
    #include <vector>
    #include <algorithm>
    #include <map>
    #include <iostream>
    #define inf 0x3f3f3f3f
    #define inf64 0x3f3f3f3f3f3f3f3f
    using namespace std;
    const int maxn = 5e5 + 10;
    typedef long long ll;
    
    int main(){
        ll a,b,c,x,y,z;
        cin>>a>>b>>c>>x>>y>>z;
        printf("%lld
    ",min(a,y)+min(b,z)+min(x,c));
        return 0;
    }
    A

    B.排数字

    这也是个签到题。

    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <queue>
    #include <vector>
    #include <algorithm>
    #include <map>
    #include <iostream>
    #define inf 0x3f3f3f3f
    #define inf64 0x3f3f3f3f3f3f3f3f
    using namespace std;
    const int maxn = 5e5 + 10;
    typedef long long ll;
    char s[maxn];
    
    int main(){
        int n;
        scanf("%d%s",&n,s+1);
        int num1=0,num6=0;
        for(int i=1;i<=n;i++){
            int x=s[i]-'0';
            if(x==1) num1++;
            if(x==6) num6++;
        }
        printf("%d
    ",min(num1,num6-1));
        return 0;
    }
    B

    C.算概率

    这是一个概率dp。

    dp[i][j] 表示前面i个题目做出了j个的概率

    dp[i][j]=dp[i-1][j-1]*p[i]+dp[i-1][j]*(1-p[i])

    这个题目卡了我一会,很少写概率dp,不太会写。

    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <queue>
    #include <vector>
    #include <algorithm>
    #include <map>
    #include <iostream>
    #define inf 0x3f3f3f3f
    #define inf64 0x3f3f3f3f3f3f3f3f
    using namespace std;
    const int maxn = 2e3 + 10;
    typedef long long ll;
    const int mod=1e9+7;
    const int maxs=1e9+8;
    ll dp[maxn][maxn],p[maxn];
    
    int main(){
        int n;
        scanf("%d",&n);
        for(int i=1;i<=n;i++) scanf("%lld",&p[i]);
        dp[0][0]=1;
        for(int i=1;i<=n;i++){
            for(int j=0;j<=i;j++){
                dp[i][j]=dp[i-1][j]*(maxs-p[i])%mod;
                if(j>0) dp[i][j]+=dp[i-1][j-1]*p[i]%mod;
                dp[i][j]%=mod;
            }
        }
        for(int i=0;i<=n;i++){
            printf("%lld ",dp[n][i]);
        }
        return 0;
    }
    C

    D.数三角

    这个就是一个余弦定理,注意判断能否构成三角形。

    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <queue>
    #include <vector>
    #include <algorithm>
    #include <cmath>
    #include <map>
    #include <iostream>
    #define inf 0x3f3f3f3f
    #define inf64 0x3f3f3f3f3f3f3f3f
    using namespace std;
    const int maxn = 2e3 + 10;
    typedef long long ll;
    const int mod=1e9+7;
    const int maxs=1e9+8;
    const long double eps=1e-6;
    long double x[maxn],y[maxn];
    long double dis(int i,int j){
        return sqrt((x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]));
    }
    long double deal(long double a,long double b,long double c){
        return (b*b+c*c-a*a)/(2*b*c);
    }
    
    int main(){
        int n,ans=0;
        scanf("%d",&n);
        for(int i=1;i<=n;i++) scanf("%Lf%Lf",&x[i],&y[i]);
        for(int i=1;i<=n;i++){
            for(int j=i+1;j<=n;j++){
                for(int k=j+1;k<=n;k++){
                    long double a=dis(i,j),b=dis(j,k),c=dis(i,k);
                    long double num1=deal(a,b,c),num2=deal(b,c,a),num3=deal(c,a,b);
                    if(b+c<=a) continue;
                    if(a+c<=b) continue;
                    if(b+a<=c) continue;
                    if(num1<0||num2<0||num3<0) ans++;
                }
            }
        }
        printf("%d
    ",ans);
        return 0;
    }
    D

    E.做计数

    这个平方一下就知道要满足i*j 是一个平方数才行,所以枚举所有的平方数,

    然后求出每一个平方数的约数即可,这平方数的约数个数就是[i,j]的组数。

    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <queue>
    #include <vector>
    #include <algorithm>
    #include <cmath>
    #include <map>
    #include <iostream>
    #define inf 0x3f3f3f3f
    #define inf64 0x3f3f3f3f3f3f3f3f
    using namespace std;
    const int maxn = 2e4 + 10;
    typedef long long ll;
    int 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];
            }
        }
    }
    int main(){
        init1();
        int ans=0,n;
        scanf("%d",&n);
        for(ll i=1;i*i<=n;i++){
            ll x=i*i,res=1;
            for(int j=0;j<m;j++){
                int p=1;
                while(x%isp[j]==0) x/=isp[j],p++;
                res*=p;
            }
            ans+=res;
        }
        printf("%d
    ",ans);
    }
    E

    F.拿物品

    这个是一个贪心,这个贪心把我人绕晕了,差点没有反应过来。

    对于一个物品,我们不仅需要a越大越好,而且b也越大越好,所以应该按照a+b排序。

    可以理解为,如果a越大自己得到的就越多,如果b越大,那么别人失去的也就越多,所以a+b越大越好。

    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <queue>
    #include <vector>
    #include <algorithm>
    #include <cmath>
    #include <map>
    #include <iostream>
    #define inf 0x3f3f3f3f
    #define inf64 0x3f3f3f3f3f3f3f3f
    using namespace std;
    const int maxn = 2e5 + 10;
    typedef long long ll;
    struct node{
        ll a,b,d,id;
    }w[maxn],v[maxn];
    int ans1[maxn],ans2[maxn],vis[maxn];
    bool cmp(node a,node b){
        return a.b+a.a>b.a+b.b;
    }
    int main(){
        int n,cnt1=0,cnt2=0;
        scanf("%d",&n);
        for(int i=1;i<=n;i++) scanf("%lld",&w[i].a),w[i].id=i;
        for(int i=1;i<=n;i++) scanf("%lld",&w[i].b);
        sort(w+1,w+1+n,cmp);
        for(int i=1;i<=n;i+=2){
            ans1[++cnt1]=w[i].id;
            if(i==n) break;
            ans2[++cnt2]=w[i+1].id;
        }
        for(int i=1;i<cnt1;i++) printf("%lld ",ans1[i]);
        printf("%lld
    ",ans1[cnt1]);
        for(int i=1;i<cnt2;i++) printf("%lld ",ans2[i]);
        printf("%lld
    ",ans2[cnt2]);
        return 0;
    }
    F

    G.判正误

    这个题目知道是哈希就很简单了。

    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <queue>
    #include <vector>
    #include <algorithm>
    #include <cmath>
    #include <map>
    #include <iostream>
    #define inf 0x3f3f3f3f
    #define inf64 0x3f3f3f3f3f3f3f3f
    using namespace std;
    const int maxn = 2e3 + 10;
    typedef long long ll;
    const int mod=13331;
     
    ll quick_pow(ll a,ll b,ll mod)
    {
        ll ans = 1;
        while(b)
        {
            if (b & 1) ans = (ans*a)%mod;
            a = (a*a)%mod;
            b >>= 1;
        }
        return ans;
    }
     
     
     
    int main(){
        int t;
        scanf("%d",&t);
        while(t--){
            ll a,b,c,d,e,f,g;
            cin>>a>>b>>c>>d>>e>>f>>g;
            ll num1=quick_pow(a,d,mod),num2=quick_pow(b,e,mod),num3=quick_pow(c,f,mod);
            ll num=(num1+num2+num3)%mod;
            if(num==g%mod) printf("Yes
    ");
            else printf("No
    ");
        }
    }
    G

    H.施魔法

    这个题目是一个类似于线段树优化dp,但是我不太会写,因为自己想的有点复杂了。

    其实写法很简单,这个是我看lj的代码写的,以后可以再看看。

    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <queue>
    #include <vector>
    #include <algorithm>
    #include <cmath>
    #include <map>
    #include <iostream>
    #define inf 0x3f3f3f3f
    #define inf64 0x3f3f3f3f3f3f3f3f
    using namespace std;
    const int maxn = 3e5 + 10;
    typedef long long ll;
    ll mins[maxn*4],a[maxn];
    void build(int id,int l,int r){
        mins[id]=inf64;
        if(l==r) return ;
        int mid=(l+r)>>1;
        build(id<<1,l,mid);
        build(id<<1|1,mid+1,r);
    }
    void push_up(int id){
        mins[id]=min(mins[id<<1],mins[id<<1|1]);
    }
    
    ll query(int id,int l,int r,int x,int y){
        if(y<l||x>r) return inf;
        if(x<=l&&y>=r) return mins[id];
        ll ans=inf,mid=(l+r)>>1;
        if(x<=mid) ans=min(ans,query(id<<1,l,mid,x,y));
        if(y>mid) ans=min(ans,query(id<<1|1,mid+1,r,x,y));
        return ans;
    }
    void modify(int id,int l,int r,int pos,ll val){
        if(pos<l||pos>r) return ;
        if(l==r){
            mins[id]=val;
            return ;
        }
        int mid=(l+r)>>1;
        if(pos<=mid) modify(id<<1,l,mid,pos,val);
        else modify(id<<1|1,mid+1,r,pos,val);
        push_up(id);
    }
    int main(){
        int n,k;
        scanf("%d%d",&n,&k);
        for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
        sort(a+1,a+1+n);
        for(int i=1;i<=n;i++){
            ll x=a[i]-a[1];
            x=min(x,a[i]+query(1,1,n,k,i-k));
            if(i==n) printf("%lld
    ",x);
            else modify(1,1,n,i,x-a[i+1]);
        }
        return 0;
    }
    H

    I.建通道

    这个可以说是一个简单题了,首先判断出数字的种类,因为如果数字相同可以0花费连在一起,

    然后判断出奇偶,如果有奇数也有偶数,那么答案就是数字种类数-1

    如果都是偶数,那就整体右移一位,ans*=2,这个时候有奇数有偶数的话,答案就是(种类数-1)*ans【ans的初始化为1】

    J.求函数

    这也是一个线段树,不过我不是很会写,后来看了题解发现就是如何合并两个区间。

    这个题解说的很详细。https://ac.nowcoder.com/discuss/364961?type=101&order=0&pos=1&page=3

    这个以后可以再看看。

    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <queue>
    #include <vector>
    #include <algorithm>
    #include <cmath>
    #include <map>
    #include <iostream>
    #define inf 0x3f3f3f3f
    #define inf64 0x3f3f3f3f3f3f3f3f
    using namespace std;
    typedef long long ll;
    const int maxn = 2e5 + 10;
    const int mod=1e9+7;
    ll sum1[maxn*4],sum2[maxn*4],k[maxn],b[maxn];
    void push_up(int id){
        sum1[id]=sum1[id<<1]*sum1[id<<1|1]%mod;
        sum2[id]=(sum1[id<<1|1]*sum2[id<<1]%mod+sum2[id<<1|1]%mod)%mod;
    }
    void build(int id,int l,int r){
        if(l==r){
            sum1[id]=k[l];
            sum2[id]=b[l];
            return ;
        }
        int mid=(l+r)>>1;
        build(id<<1,l,mid);
        build(id<<1|1,mid+1,r);
        push_up(id);
    }
    
    void modify(int id,int l,int r,int pos,ll k,ll b){
        if(l==r){
            sum1[id]=k%mod;
            sum2[id]=b%mod;
            return ;
        }
        int mid=(l+r)>>1;
        if(pos<=mid) modify(id<<1,l,mid,pos,k,b);
        else modify(id<<1|1,mid+1,r,pos,k,b);
        push_up(id);
    }
    ll ans;
    void query(int id,int l,int r,int x,int y){
        if(x<=l&&y>=r){
            ans=(ans*sum1[id]%mod+sum2[id])%mod;
            return ;    
        }
        int mid=(l+r)>>1;
        if(x<=mid) query(id<<1,l,mid,x,y);
        if(y>mid) query(id<<1|1,mid+1,r,x,y);
    }
    int main(){
        int n,m;
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++) scanf("%lld",&k[i]);
        for(int i=1;i<=n;i++) scanf("%lld",&b[i]);
        build(1,1,n);
        while(m--){
            ll k1,b1;
            int opt,i,l,r;
            scanf("%d",&opt);
            if(opt==1){
                scanf("%d%lld%lld",&i,&k1,&b1);
                modify(1,1,n,i,k1,b1);
            }
            else{
                ans=1;
                scanf("%d%d",&l,&r);
                query(1,1,n,l,r);
                printf("%lld
    ",ans);
            }
        }
        return 0;
    }
    J
  • 相关阅读:
    我渴望自由和成功(愿与君共勉)
    gdb使用 和core dump文件调试
    谷歌浏览器快捷键大全
    Android适屏
    BestCoder Round #33
    NAT&amp;Port Forwarding&amp;Port Triggering
    程序员应该学习的书
    java代码调用rtx发送提醒消息
    js实现excel导出
    一个跨界程序员:不务正业的这几年,我如何让自己的收入翻了十倍(转)
  • 原文地址:https://www.cnblogs.com/EchoZQN/p/12273060.html
Copyright © 2011-2022 走看看