zoukankan      html  css  js  c++  java
  • Codeforces Round #643 (Div. 2) 题解

    A

    猜一手不会经过很多次就会有(Min=0),然后写个暴力就好了。

    ll calc(ll n,ll k)
    {
        ll ans=n;
        while (k--)
        {
            int mn=10,mx=0;ll tmp=ans;
            while (tmp)
            {
                int x=tmp%10;tmp/=10;
                mn=min(mn,x);mx=max(mx,x);
            }
            if (!mn) return ans;
            else ans+=mn*mx;
        }
        return ans;
    }
    
    int main()
    {
        int T=read();
        while (T--)
        {
            ll n=readll(),k=readll();
            printf("%lld
    ",calc(n,k-1));
        }
        return 0;
    }
    

    B

    将序列从小到大排序之后能分组就分组。

    int n,a[300300];
    
    int main()
    {
        int T=read();
        while (T--)
        {
            n=read();
            rep(i,1,n) a[i]=read();
            sort(a+1,a+1+n);
            int ans=0,now=0;
            rep(i,1,n)
            {
                now++;
                if (now>=a[i]) 
                {
                    now=0;ans++;
                }
            }
            printf("%d
    ",ans);
        }
        return 0;
    }
    

    C

    枚举(x),之后对于每个(y),合法的(z)都是区间([C,min(x+y-1,D)])中的数。

    考虑先求出这个右边界的取值范围,再加上使(zin[C,D])的区间的贡献即可。

    int calc(int x,int y,int zl,int zr)
    {
        int nowl=zl,nowr=x+y-1;
        int ans=nowr-nowl+1;
        ans=max(0,ans);ans=min(ans,zr-zl+1);
        return ans;
    }
    
    int main()
    {
        int a=read(),b=read(),c=read(),d=read();
        ll ans=0;
        rep(i,a,b)
        {
            int x=i;
            int L=calc(x,b,c,d),R=calc(x,c,c,d);
            ans+=1ll*(R-L+1)*(L+R)/2;
            int tmp=d-x+1;
            if (tmp>=c) continue;
            tmp=max(b,tmp);
            if (tmp+1<=c)
            {
                ans+=1ll*(d-c+1)*(c-tmp);
            }
        }
        printf("%lld
    ",ans);
    }
    

    D

    构造序列(1,1,cdots ,1,m-(n-1)).之后询问的(k=m-n),正确性显然。

    int main()
    {
        int n=read(),m=read();
        if (m<n*2) {puts("NO");return 0;}
        puts("YES");
        rep(i,1,n-1) printf("1 ");
        printf("%d
    ",m-(n-1));
        printf("%d
    ",m-(n-1)-1);
    }
    

    E

    介绍一个猎奇做法。

    先只考虑add/remove操作,我们可以枚举终止状态时的高度(Hin[h_i,h_{i+1}]),那么(H)(+1)(-1)都只会引起两种操作的固定数量的操作次数发生变化,于是最优花费只会在区间的两个端点取到。

    再考虑move操作,注意到如果使用了这一操作就会一直使用到底,也就是最终add/remove操作只会剩下至多一个,我们可以二分一个位置(h'),使得若(Hleq h')则remove操作的次数(geq)add操作的次数。也就是此时只会有move和remove操作,变成了最开始的情况。(H>h')的也是类似的。

    然后被三分哥按在地上摩擦

    #define int long long
    
    int n,a[100100];
    ll A,R,M,s[100100];
    
    ll calc(int goal,int p)
    {
        ll ca=1ll*goal*p-s[p],cr=s[n]-s[p]-1ll*(n-p)*goal;
        ll ans=ca*A+cr*R;
        ll cm=min(ca,cr);
        ans=min(ans,max(0ll,(cr-cm)*R)+max(0ll,(ca-cm))*A+cm*M);
        return ans;
    }
    
    ll solve(int vL,int vR,int p)
    {
        ll ans=min(calc(vL,p),calc(vR,p));
        int l=vL,r=vR,pos=vL;
        while (l<=r)
        {
            int mid=(l+r)>>1;
            ll cr=s[n]-s[p]-1ll*mid*(n-p),ca=1ll*p*mid-s[p];
            if (cr>=ca) {pos=mid;l=mid+1;}
            else r=mid-1;
        }
        rep(i,-3,3)
            if ((pos+i>=vL) && (pos+i<=vR)) ans=min(ans,calc(pos+i,p));
        return ans;
    }
    
    
    signed main()
    {
        n=read();A=read();R=read();M=read();
        rep(i,1,n) a[i]=read();
        sort(a+1,a+1+n);
        rep(i,1,n) s[i]=s[i-1]+a[i];
        ll ans=4e18;
        rep(i,1,n-1) ans=min(ans,solve(a[i],a[i+1],i));
        printf("%lld
    ",ans);
        return 0;
    }
    

    F

    神必题

    最naive的想法是按照每个质数去找,也就是每次询问一个(p^q),显然gg。

    稍微思考一下发现只要找(sqrt n)的质数,并且可以将一些质数乘在一起询问,再在最后确定每个质数的次幂。但是貌似完成前一步就需要(22)次询问,依然不行。

    继续往下考虑,注意到(N)至多只会有(9)个不同的质因子,我们可以留(5)次询问来处理次幂。剩下的(17)次询问可以全部用来处理小的质因数,笔者的写法可以处理(<683)的质因子。

    那么对于比它还大的呢?此时若这个数有(leq 2)个这样的质因数,我们可以直接将答案( imes 2),而对于(3)个的情况,可以分情况讨论:

    • 不再含有其它的质因子,那么最终答案(=8),可以直接(+7).

    • 含有其它的质因子,那么这个质因子只能为(2),也就是最终答案(=16=2+7+7),我们仍然可以将之前得到的答案(+7).

    综上所述,记处理小质因数得到的答案为(x),则返回(max(2x,x+7)).

    int tot,pri[2002000];
    ll maxd=1e18,maxd1=1e9;
    bool nopri[2002000];
         
    ll ask(ll x)
    {
        printf("? %lld
    ",x);fflush(stdout);
        ll y;scanf("%lld",&y);
        return y;
    }
         
    void sieve(int n)
    {
        rep(i,2,n)
        {
            if (!nopri[i]) pri[++tot]=i;
            for (int j=1;j<=tot && i*pri[j]<=n;j++)
            {
                nopri[i*pri[j]]=1;
                if (i%pri[j]==0) continue;
            }
        }
    }
         
    vi d;
    int ok=1;
         
    void solve()
    {
        d.clear();
        int used=0;ll prod=1;
        int lst=1;
        rep(i,1,tot)
        {
            if (maxd/pri[i]<prod)
            {
                ll now=ask(prod);used++;prod=1;
                assert(now>0);
                if (now!=1)
                {
                    ll tmp=now;
                    for (int j=lst;1ll*pri[j]*pri[j]<=tmp && j<i;j++)
                    {
                        if (tmp%pri[j]) continue;
                        while (tmp%pri[j]==0) tmp/=pri[j];
                        d.pb(pri[j]);
                    }
                    if (tmp!=1) d.pb(tmp);
                }
                if (used==17) break;lst=i;
            }
            prod*=pri[i];
        }
        int len=d.size();int ans=1;
        if (len&1) d.pb(1);
        for (int i=0;i<len;i+=2)
        {
            ll now=1;
            int d1=d[i],d2=d[i+1];
            while (maxd1/now>=d1) now*=d1;
            if (d2!=1)
                while (maxd/now>=d2) now*=d2;
            ll tmp=ask(now);used++;
            int c=0;
            while (tmp%d1==0)
            {
                tmp/=d1;c++;
            }
            ans*=(c+1);
            c=0;
            if (d2==1) continue;
            while (tmp%d2==0)
            {
                tmp/=d2;c++;
            }
            ans*=(c+1);
        }
        ans=max(ans+7,ans*2);
        printf("! %d
    ",ans);fflush(stdout);
    }
         
    int main()
    {
        sieve(1000);
        int T=read();
        while (T--) solve();
        return 0;
    }
    
  • 相关阅读:
    make[1]: *** [/workopenwrt/trunk/staging_dir/target-mipsel_24kec+dsp_uClibc-0.9.33.2/stamp/.tools_install_nnnnn] Error 2 make[1]: Leaving directory `/work/openwrt/trunk' make: *** [world]
    安卓端与开发板通信
    openwrt串口的使用
    .OpenWrt驱动程序Makefile的分析概述 、驱动程序代码参考、以及测试程序代码参考
    openwrt系统之字符设备驱动软件包加载、测试程序加载
    cc2530串口通信流程
    cc2530操作任务系统初始化分析
    总结OpenWrt系统基本操作方法
    Zigbee协议栈OSAL层API函数【转载】
    cc2530启动流程---广播发送数据
  • 原文地址:https://www.cnblogs.com/encodetalker/p/12903184.html
Copyright © 2011-2022 走看看