Codeforces-Div3-653(A~E1)

A. Required Remainder

题意:

TT组询问,给定x,y,n(2x109;0y<x;yn109)x,y,n (2≤x≤10^9; 0≤y<x; y≤n≤10^9),求最大的整数kk,满足0knkmodx=y0≤k≤n且k mod x=y

思路:

转换公式 k=k1x+yk1Rk=k1*x+y,k1∈R ,则需要找到最大的k1k1,使得k1x+y<=nk1*x+y<=n,则k1max=(ny)/xk1_{max}=(n-y)/x,套入第一个式子即可。

Code:

int main(){
    int t;
    t=read();
    while(t--){
         ll x,y,n;
         scanll3(x,y,n);
         printf("%lld\n",(n-y)/x*x+y);
    }
	return 0;
}

B. Multiply by 2, divide by 6

题意:

TT组询问,给定一个n,1n109n,1≤n≤10^9,每次操作将nn66(能被66整除),或者将nn22。问最少多少次操作可以将nn变换乘11。否则输出1-1

思路:

暴力+贪心,当前能除66就除,否则乘2,1-1的情况在暴力的情况下设置上界是不会超时的。然而正确的解法是数学,这里不做描述。

Code:

int main(){
    int t;
    t=read();
    while(t--){
        ll n;
        n=read();
        int f=0;
        if(n==1){
            puts("0");
            continue;
        }
        int cnt=0;
        while(n!=1&&n<=1e9){//n<=1e9上界
            if(n%6==0){
                n/=6;
                cnt++;
            }
            else {
                n*=2;
                cnt++;
            }
        }
        if(n!=1)puts("-1");
        else printf("%d\n",cnt);
    }
	return 0;
}

C. Move Brackets

题意:

TT组询问,每组给定一个长度为nn的括号字符串,一个括号字符串合法定义如下:

  • "()""()" is regular bracket sequence;
  • if ss regular bracket sequence then "("+s+")""(" + s+")" is regular bracket sequence;
  • if ss and tt are regular bracket sequences then ss + tt is regular bracket sequence.

每次移动可以将一个括号移动至头部或者尾部,问最少多少次移动使得给定字符串合法。输入满足,nn是偶数,有n2\frac{n}{2}))n2\frac{n}{2}((

思路:

先做括号匹配,考虑需要移动的情况,需要移动的字符串一定是)))...((()))...(((的形式,那么做法就很显然了,正常做括号匹配,需要移动的次数就是最后栈大小的一半。

Code:

int main(){
    int t;
    t=read();
    while(t--){
        ll n;
        n=read();
        stack<char>Q;
        string s;
        cin>>s;
        rep(i,0,n-1){
            if(Q.empty()){
                Q.push(s[i]);
                continue;
            }
            char tp=Q.top();
            if(s[i]==')'&&tp=='('){
                Q.pop();
                continue;
            }
            Q.push(s[i]);
        }
        cout<<Q.size()/2<<"\n";
    }
	return 0;
}

D. Zero Remainder Array

题意:

给一个长度为nn的数组aa,起初,有一个整数x=0x=0,每一次操作可以选择将数组中的一个数aiai=ai+xa_i,a_i=ai+x,随后x=x+1x=x+1,或者只执行x=x+1x=x+1,问需要最少多少次操作使数组aa中的数都能整除kk

思路:

可以看出,每个数aia_i需要加上某个xix_i,才能被kk整除。前kk次操作,可以使得那些只出现了一次xix_i的全部与之对应的aia_i变为kk的倍数,前2k2k次操作,可以使得那些只出现了两次xix_i的全部与之对应的aia_i变为kk的倍数…

预处理出每个数aia_i需要的xix_i,当xix_i相同的个数为cntxicnt_{x_i}时,需要执行到xi+(cntxi1)kx_i+(cnt_{x_i}-1)k次…
所以答案就是,维护出最大的(cntxi1)(cnt_{x_i}-1),表示要执行多少次kk,再维护出最大的xix_i,需要再执行xix_i次,最后再加11即可(00开始的第一步)。

ps:个人写的比较复杂,仅供参考。

Code:

ll q[N];
map<ll,ll>mp;
int main(){
   int t;
   t=read();
   while(t--){
       ll n;
       n=read();
       ll k;
       k=read();
       ll maxxy=-3e18;//最大xi
       ll maxxz=-3e18;//执行k多少次
       int f=0;
       rep(i,1,n){
           q[i]=read();
           ll y=((k-q[i])%k+k)%k;//xi
          //debug(y);
           if(y==0){
               continue;
           }
           f=1;
           if(mp[y]==0){
               mp[y]++;
           }
           else{
               mp[y+k*mp[y]]=mp[y]+1;
               mp[y]++;
           }
       }
       if(f==0){
           puts("0");
           mp.clear();
           continue;
       }
       for(auto it : mp){
           maxxz=max(maxxz,it.second);
       }
       for(auto it : mp){
           if(it.second==maxxz)
           maxxy=max(maxxy,((it.first)%k));//最大的xi
       }
       printf("%lld\n",(maxxz-1ll)*k+maxxy+1ll);
       mp.clear();
   }
   return 0;
}

E1. Reading Books (easy version)

题意:

给定nn本书,每本书有33个属性,分别表示t,a,bt,a,b,读这本数需要的时间,是否被Alice喜欢,是否被Bob喜欢。
两人必须一起读书,必须同时有书在手上。找出一种方案,使得Alice和Bob至少读kk本书,问最少的读书时间。

思路:

这题偏向理解,赛时没注意到不会出现一人没书读的情况,疯狂WA5,最后自闭。

  • 首先对于两者都不喜欢的书,可以直接忽略。
  • 考虑贪心,将其他三种书分类排序(从小到大)。
    • 两者都喜欢的书所需最短时间A喜欢的书的最短时间+B喜欢的书的最短时间,选两者都喜欢的最少时间的。
    • 两者都喜欢的书所需最短时间>>A喜欢的书的最短时间+B喜欢的书的最短时间,选一本A喜欢的最少时间的,一本B喜欢的最少时间的。
    • A喜欢的书已经取完了或者B喜欢的书已经取完了,则只能选一本两者都喜欢的书。

如果觉得数组模拟困难可以考虑multiset或者优先队列queue维护。

Code:

ll q[N];
ll a[N];
ll b[N];
ll t[N];
multiset<ll>s1,s2,s3;
multiset<ll>::iterator it;
int main(){
    int n;
    n=read();
    int k;
    k=read();
    int cnt=0;
    rep(i,1,n){
        scanll3(t[i],a[i],b[i]);
        if(a[i]==0&&b[i]==1){
            s3.insert(t[i]);
            cnt++;
        }
        if(a[i]==1&&b[i]==1){
            s2.insert(t[i]);
            cnt+=2;
        }
        if(a[i]==1&&b[i]==0){
            s1.insert(t[i]);
            cnt++;
        }
    }
    int con=0;
    ll ans=0;
    int cnt1,cnt2;
    cnt1=cnt2=0;
 
    while(1){
        long long it1,it2,it3;
        it1=it2=it3=0;
        if(s1.size()!=0)it1=*(s1.begin());
        if(s2.size()!=0)it2=*(s2.begin());
        if(s3.size()!=0)it3=*(s3.begin());
        if(cnt1>=k&&cnt2>=k)break;
        if(s1.size()==0&&s2.size()==0&&s3.size()==0)break;
        if((it1==0||it3==0)&&it2==0)break;
        if(it1+it3<it2&&it1!=0&&it2!=0&&it3!=0){
            if(it1!=0)cnt1++;
            if(it3!=0)cnt2++;
            ans+=it1+it3;
            it=s1.find(it1);
            s1.erase(it);
            it=s3.find(it3);
            s3.erase(it);
 
        }
        
        else if(it1+it3>=it2&&it1!=0&&it2!=0&&it3!=0){
            cnt1++;
            cnt2++;
            ans+=it2;
            it=s2.find(it2);
            s2.erase(it);
        }
        
            else if(it1==0&&it3==0&&it2!=0){
                cnt1++;
                cnt2++;
                ans+=it2;
                it=s2.find(it2);
                s2.erase(it);
            }
            else if(it1!=0&&it3!=0&&it2==0){
                cnt1++;
                cnt2++;
                ans+=it1+it3;
                it=s1.find(it1);
                s1.erase(it);
                it=s3.find(it3);
                s3.erase(it);
 
            }
            else if(it1!=0&&it3==0&&it2!=0){
                cnt1++;
                cnt2++;
                ans+=it2;
                it=s2.find(it2);
                s2.erase(it);
            }
            else if(it1==0&&it3!=0&&it2!=0){
                cnt1++;
                cnt2++;
                ans+=it2;
                it=s2.find(it2);
                s2.erase(it);
        }
        //debug(ans);
    }   
    if(cnt1<k||cnt2<k){
        cout<<"-1";
        return 0;
    }
    cout<<ans;
 
    return 0;
}

小坑点:

值得一提的是,multiset中的erase(x),如果x是元素值,会将多个x全部删去,而不是只删去一个。正确的做法,是先find(x)找到迭代器再erase即可。
此题使用优先队列会更为方便。如果用multiset必须注意如上小坑点,否则你会因此不断WA5…

其他题待补
展开阅读全文

Windows版YOLOv4目标检测实战:训练自己的数据集

04-26
©️2020 CSDN 皮肤主题: 游动-白 设计师: 上身试试 返回首页
实付0元
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值