CF Round701-div2(CF1485)

A-Add and Divide

  题意:给出两个数,a和b,有两种操作,一种是a/b(计算机整除,只保留整数位),另一种是b+1,求最少通过多少次操作可以使得a==0。

  题解:

  1. BFS。
  2. (UPD:2021-02-13-17:14)可以得出对于每一步的操作,先增加b,再去除,整体会比先除在增加更优,因为 a/b > a/(b+1)。solve2()即为30ms写法。
  3. (UPD:2021-02-15-00:30通过观察可以发现,solve2()中的内层循环,其实是可以通过计算对数直接获得,不需要一个一个除。
 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 #define rep(i,a,n) for (int i=a;i<n;i++)
 4 #define mp make_pair
 5 #define fi first
 6 #define se second
 7 typedef long long ll;
 8 typedef pair<int,int> PII;
 9 typedef pair<int,PII>piii;
10 int t,a,b;
11 queue<piii>q;
12 void solve1(){            //93ms, 3700KB写法 
13     while(!q.empty()) q.pop();
14         cin>>a>>b;
15         q.push(mp(a,mp(b,0)));
16         int cnt=0;
17         while(!q.empty()){
18             piii tp=q.front();q.pop();
19             if(tp.fi==0){
20                 cout<<tp.se.se<<endl;
21                 break;
22             }
23             int cnt=tp.se.se;
24             //++cnt;
25             int ta=tp.fi,tb=tp.se.fi;
26             q.push(mp(ta/tb,mp(tb,cnt+1)));
27             q.push(mp(ta,mp(tb+1,cnt+1)));
28         }
29 }
30 
31 void solve2(){            //30ms,0KB写法 
32     cin>>a>>b;
33     if(a==0) {
34         cout<<0<<endl;
35         return;
36     }
37     int res=a+3;
38     for(int i=0;i<res;++i){
39         int ans=i,bcs=a,cs=i+b;
40         if(cs==1) continue;
41         while(bcs) bcs/=cs,++ans;
42         res=min(res,ans);
43     }
44     cout<<res<<endl;
45 }
46 int main(){
47     cin>>t;
48     while(t--)
49     {
50         //solve1();   
51         solve2(); 
52     } 
53     return 0;
54 }    
View Code

 

 

B-Replace and Keep Sorted

  题意:给出一串数列a,求有多少种不同的数列b,使得a与b只有一个数不同,而且b保持严格单调递增,所有数的取值区间为[1,k]。

  题解:

    • 等价于求对于原数列a,每个元素可以增加或减小的备选可能数。
    • 可以用一个新的数组来保存a中每个元素可动范围,b[i]=a[i+1]-a[i-1]-1
    • L端点的可动范围应该是1~a[L+1]-1,R端点的可动范围是a[R-1]+1~k。
    • 由于题目中每次查询都是区间查询,所以可以使用一个线段树进行维护,有因为查询区间的端点的种类数与非端点的计算方法不同,所以每次查询[L+1,R-1],然后在加上端点的种类数。
 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 #define rep(i,a,n) for (int i=a;i<n;i++)
 4 #define lson (rt<<1)
 5 #define rson (rt<<1 | 1)
 6 #define gmid (l+r >> 1)
 7 typedef long long ll;
 8 const int mod = 1e9+7;
 9 int n,q,k,l,r;
10 int a[100500];
11 int b[100500];
12 ll sum[400500];
13 void pushup(int rt)
14 {
15     sum[rt]=(sum[lson]+sum[rson]);
16 }
17 void build(int l,int r,int rt)
18 {
19     if(l==r)
20     {
21         sum[rt]=b[l];
22         return;
23     }
24     int mid=gmid;
25     build(l,mid,lson);
26     build(mid+1,r,rson);
27     pushup(rt);
28 }
29 int query(int l,int r,int L,int R,int rt)        //区间查询
30 {
31     ll ans=0;
32     if(L<=l && r<=R)
33     {
34         return sum[rt];
35     }
36     int mid=gmid;
37     if(L<=mid) ans=(ans+query(l,mid,L,R,lson));
38     if(R>mid) ans=(ans+query(mid+1,r,L,R,rson));
39     return ans;
40 }
41 int main(){
42     cin>>n>>q>>k;
43     rep(i,1,n+1) cin>>a[i];
44     rep(i,1,n+1)
45         b[i]=(i==n?k+1:a[i+1])-(i==1?0:a[i-1])-2;
46        build(1,n,1);
47        rep(i,1,q+1){
48            cin>>l>>r;
49            if(l==r) cout<<k-1<<endl;
50            else cout<<query(1,n,l+1,r-1,1)+a[l+1]-2+k-a[r-1]-1<<endl;
51     }
52     return 0;
53 }
View Code

 

C-Floor and Mod

  题意: 定义一对有序整数对(a,b)符合:a/b = a mod b 为特殊对,其中 a/b 为计算机整除。要求 a∈[1,x],b∈[1,y]的前提下,有多少对特殊对。

  题解:令 a/b = a mod b = k,则 a = b*k + k,其中b > k,缩放后:k*k ≤ b*k+k = a,所以 k ≤ x0.5,对于一个确定的k,求(a,b) 的可行对数。

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 #define rep(i,a,n) for (long long i=a;i<n;i++)
 4 typedef long long ll;
 5 ll t,a,b,x,y,ans=0;
 6 double eu=0.577215664901;
 7 int main(){
 8     cin>>t;
 9     while(t--)
10     {
11         cin>>x>>y;
12         for(ll i=1;i*i<x;++i) ans+=max(0ll,min(y,x/i-1)-i); 
13         cout<<ans<<endl;
14         ans=0;
15     }
16     return 0;
17 }
View Code

 

D-Multiples and Power Differences

  题意:给出一个矩阵A,其中A的每个元素都不大于16。要求构造一个新的矩阵B,使得:

    • 使得B的行数与列数等于A
    • B中的每个元素都是A中对应元素的倍数
    • B中每个元素与其相邻元素的差,是一个四次方数,即差值等于k4,k∈N。

  题解:

    • 由于A中每个元素都不大于16,那么求一下lcm(1,...,16)=720720,让B矩阵的数全部等于720720,就解决了第二个条件。
    • 在从现有的数修改,要使得元素与四周的元素相差是一个k4,而且保持倍数关系,那就可以让四周的数等于720720,然后中间数等于720720+A(i,j)4,有一个倍数加上一个倍数,依然是这个数的倍数,然后不断插空划分之后,就得到一个类似vans棋盘格的矩阵,白点全是720720,黑点全是720720+A(i,j)4
 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 int n,m;
 5 ll ma,mb;
 6 ll gcd(ll a,ll b){
 7     return b==0?a:gcd(b,a%b);
 8 }
 9 ll lcm(ll a,ll b){
10     return a/gcd(a,b)*b;
11 }
12 ll cal(ll a){
13     return a*a*a*a;
14 }
15 int main()
16 {
17     cin>>n>>m;
18     ll base=1;
19     for(ll i=1;i<=16;++i) base=lcm(base,i);
20     //cout<<base<<endl;
21     for(int i=1;i<=n;++i)
22     {
23         for(int j=1;j<=m;++j) 
24             cin>>ma,mb=(i+j)&1?base+cal(ma):base,cout<<mb<<' ';
25         cout<<endl;    
26     }
27     return 0;
28 }
View Code

 

 

(EF还没做,晚点补。)

(如有错漏,欢迎友好交流指正)

 

posted @ 2021-02-13 13:23  Alex_Chao  阅读(166)  评论(4编辑  收藏  举报