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写法。

        代码:

#include 
using namespace std;
#define rep(i,a,n) for (int i=a;i PII;
typedef pairpiii;
int t,a,b;
queueq;
void solve1(){            //93ms, 3700KB写法
    while(!q.empty()) q.pop();
        cin>>a>>b;
        q.push(mp(a,mp(b,0)));
        int cnt=0;
        while(!q.empty()){
            piii tp=q.front();q.pop();
            if(tp.fi==0){
                cout<>a>>b;
    if(a==0) {
        cout<<0<>t;
    while(t--)
    {
        //solve1();
        solve2();
    }
    return 0;
}

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],然后在加上端点的种类数。

        代码:

#include 
using namespace std;
#define rep(i,a,n) for (int i=a;i> 1)
typedef long long ll;
const int mod = 1e9+7;
int n,q,k,l,r;
int a[100500];
int b[100500];
ll sum[400500];
void pushup(int rt)
{
    sum[rt]=(sum[lson]+sum[rson]);
}
void build(int l,int r,int rt)
{
    if(l==r)
    {
        sum[rt]=b[l];
        return;
    }
    int mid=gmid;
    build(l,mid,lson);
    build(mid+1,r,rson);
    pushup(rt);
}
int query(int l,int r,int L,int R,int rt)        //区间查询
{
    ll ans=0;
    if(L<=l && r<=R)
    {
        return sum[rt];
    }
    int mid=gmid;
    if(L<=mid) ans=(ans+query(l,mid,L,R,lson));
    if(R>mid) ans=(ans+query(mid+1,r,L,R,rson));
    return ans;
}
int main(){
    cin>>n>>q>>k;
    rep(i,1,n+1) cin>>a[i];
    rep(i,1,n+1)
        b[i]=(i==n?k+1:a[i+1])-(i==1?0:a[i-1])-2;
       build(1,n,1);
       rep(i,1,q+1){
           cin>>l>>r;
           if(l==r) cout<

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) 的可行对数。

        代码:

#include 
using namespace std;
#define rep(i,a,n) for (long long i=a;i>t;
    while(t--)
    {
        cin>>x>>y;
        for(ll i=1;i*i

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

         代码:

#include
using namespace std;
typedef long long ll;
int n,m;
ll ma,mb;
ll gcd(ll a,ll b){
    return b==0?a:gcd(b,a%b);
}
ll lcm(ll a,ll b){
    return a/gcd(a,b)*b;
}
ll cal(ll a){
    return a*a*a*a;
}
int main()
{
    cin>>n>>m;
    ll base=1;
    for(ll i=1;i<=16;++i) base=lcm(base,i);
    //cout<>ma,mb=(i+j)&1?base+cal(ma):base,cout<

你可能感兴趣的:(codeforces,蓝桥杯,c++,算法)