Codeforces Global Round 27(A-D)

 A-Sliding

思路 

可能翻译出来题意比较无语,实际上就是一个n*m的表格,第r,c走了,剩下的在他后面的点移动道他们前面的那个点的位置,问移动的麦哈顿距离,我们画图就能够发现第r+1到第n行的第一个会移动m搁,其他就是一格 

代码 

void solve() {
    ll n, m, r, c;
    cin >> n >> m >> r >> c;
    ll ans = 0;
    ans = ans + (n - r) * m;
    ll ans2 = 0;
    ans2 = ans2 + (n - r) * (m - 1) + (m - c);
    cout << ans + ans2;
}

 B-Everyone Loves Tres 

思路  

打表就行,由于找最小的被33和66整除的,我们打表就会发现,除了1,3没有答案外,

奇数为n6366

偶数维n66 

代码

void solve() {
    /*ll x = 66;打表
    for (int i = 1; i <= 10000000000; i++) {
        ll y = i * x;
        ll mark = 1;
        while (y > 0) {
            ll a = y % 10;
            if (a != 6 && a != 3) {
                mark = 0;
            }
            y = y / 10;
        }
        if (mark) {
            cout << i*x << endl;
        }
    }*/
    ll n;
    cin >> n;
    if (n == 1 || n == 3) {
        cout << "-1";
        return;
    }
    if (n % 2 == 0) {
        for (int i = 1; i <= n - 2; i++) {
            cout << "3";
        }
        cout << "66";
    }
    else {
        for (int i = 1; i <= n - 4; i++) {
            cout << "3";
        }
        cout << "6366";
    }
}

 C-Alya and Permutation

思路  

尽管有人说是打表题,但实际上可以证明,我们先令X为一个01字符串,

奇数:最后一位一定是X1,那么上一位一定是X0,由于奇数位是并操作,所以最后的答案最大就是是n,那么对于X0取或之后再对X1取并会发现少了个一,解决发放就是在n-2和n-3上面放两个奇数就可以了

偶数:最后一位应该是1X0,我们已经知道n为奇数时能创建除了,那么我们就在n-1位上去实现X0,然后最后一位取或就能够实现111111的结果了 

代码 

void solve() {
    ll n;
    cin >> n;
    ll k = 0;
    if (n & 1) {
        cout << n << endl;
        for (int i = 2; i <= n - 3; i++) {
            cout << i << " ";
        }
        cout << "1" << " " << n - 2 << " " << n - 1 << " " << n;
    }
    else {
        int ans = 0;
        for (int i = 0; i <= 100; i++) {
            ll b = ((ll)1 << i);
            if (b > n) {
                ans = b - 1;
                break;
            }
        }
        cout << ans << endl;
        ll sum1 = 0;
        for (int i = 0; powl(2, i) <= n; i++) {
            ll x = ((ll)1 << i);
            if ((x & n) == 0) {
                sum1 = sum1 | x;
            }
        }
        if (sum1 <= 3) {
            n--;
            for (int i = 2; i <= n - 3; i++) {
                cout << i << " ";
            }
            cout << "1" << " " << n - 2 << " " << n - 1 << " " << n << " " << n + 1 ;
        }
        else {
            
            map<ll, ll>brr;
            for (int i = 2; i <= sum1 - 3; i++) {
                brr[i]++;
            }
            brr[1]++;
            brr[sum1 - 2]++;
            brr[sum1 - 1]++;
            brr[sum1]++;
            for (int i = 1; i <= n - 1; i++) {
                if (brr[i] == 0) {
                    cout << i << " ";
                }
            }
            for (int i = 2; i <= sum1 - 3; i++) {
                cout << i << " ";
            }
            cout << "1" << " " << sum1 - 2 << " " << sum1 - 1 << " " << sum1 << " " << n;
        }
    }
}

D-Yet Another Real Number 问题

思路 

 算是一道模拟题吧,我们先把数字分解成不能被2整除的形式,拿样例说一遍

1 2 3 4 5 6 7 8 9 10

1 1 3 1 5 3 7 1 9 5        分解成的奇数

0 1 0 2 0 1 0 3 0 1        分解成的2的数量

那么我们从前往后走,我们发现到了一个位置,会出现一个状态,是应该让前面的一个数字去乘以他前面的2的数量还是让全部的2去乘以最后的2的数量,这个情况其实很好解决,我们到达一个位置,如果前面那个数字到达当前的数字所有的2依旧小于前面的那个数字,那就不用选当前的位置,否者,就选最后的这个位置就可以了,

用优先队列维护即可 

代码 

struct node {
    ll id = 0;
    ll sum2 = 0;
    ll x = 0;
    node() {};
    node(ll a, ll b, ll c) {
        id = a;
        x = b;
        sum2 = c;
    }
};
bool operator <(node a, node b) {
    return a.id < b.id;
}
priority_queue<node>dp;
void solve() {
    ll n;
    cin >> n;
    while (dp.size()) {
        dp.pop();
    }
    vector<vector<ll>>arr(n + 2, vector<ll>(4));
    for (int i = 1; i <= n; i++) {
        cin >> arr[i][1];//1存数字;
        ll y = arr[i][1];
        ll k = 0;
        while (y % 2 == 0) {
            k++;
            y = y / 2;
        }
        arr[i][1] = y;
        arr[i][2] = k;
    }
   /* for (int i = 1; i <= n; i++) {
        cout << arr[i][1] << " " << arr[i][2] << endl;
    }*/
    
    ll ans = 0;
    for (int i = 1; i <= n; i++) {
        //debug;
        //cout << i << endl;
        ans = ans % mod;
        while (dp.size()) {
            node now = dp.top();
            //cout << now.id << " " << now.x << " " << now.sum2 << endl;
            if (arr[i][1]*ksm(2,arr[i][2])>=now.x) {
                if (now.sum2 == 0) {
                    dp.pop();
                    continue;
                }
                arr[i][2] += now.sum2;
                ans = ans + mod - now.x*ksm(2, now.sum2) % mod;
                ans = ans + now.x;
                ans = ans % mod;
                ans = ans % mod;
                dp.pop();
            }
            else {
                break;
            }
        }
        node now = node(i, arr[i][1], arr[i][2]);
        dp.push(now);
        //cout << ans << " " << i << endl;
        ans = ans + arr[i][1] * ksm(2, arr[i][2]) % mod;
        ans = ans % mod;
        //cout << "ans="<<ans << " " << endl;
        cout << ans << " ";
    }
 
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值