Maximum Flow

这里写图片描述

数位运算
把n拆成二进制 (1xxxxxxx) 形式,对于任意 i 拆成相同位数的二进制,如果最高位是0,那么一定是可以完全流完,因为 i xor n > i (i xor n 最高位一定是1),所以可以用求和公式来求。对于最高位是1,那么后面的位数就是相当于数位的运算,计算每一位的贡献。如果当前位为1,当且 i 的对应位为0时有贡献,维护一下很容易求出有多少个合法的解;同理当前位为0。

#include <bits/stdc++.h>
using namespace std;

#define ll long long
const ll mo = 1000000007;
ll n, t, ans, a[100], g[100], l, r;

void init() {
    ans = 0;
    memset(a, 0, sizeof(a));
}


ll mul(ll x, ll y) {
    ll t = 0;
    while (y) {
        if (y%2) t = (t+x)%mo;
        y /= 2;
        x *= 2;
    }
    return t;
}

int main() {
    freopen("input.txt","r",stdin); freopen("e.out","w",stdout);
    while (scanf("%lld", &n) != EOF) {
        init();
        n--;
        t = 1;
        while (t*2 <= n) t *= 2;
        l = t%mo; r = (t-1)%mo;
        if (l%2 == 0) l /= 2;
        else r /= 2;
        ans = (l*r%mo+n%mo)%mo;
        n = n-t;
        while (n) {
            a[++a[0]] = n%2;
            n /= 2;
        }
        r = 1;
        for (int i = 1; i < a[0]; i++) r *= 2;
        l = 0;
        g[1] = 1;
        for (int i = 2; i <= a[0]; i++) g[i] = (g[i-1]*2)%mo;
        for (int i = a[0]; i >= 1; i--) {
            if (a[i]) {
                ans = (ans+(( ((l+1)%mo) * (r%mo) %mo )* (g[i]%mo) )%mo)%mo;/*2^(i-1)*/
            } else {
                ans = (ans+((l%mo) * (r%mo) %mo )*(g[i]%mo) %mo)%mo;
            }
            l = l*2+a[i];
            r = r/2;
        }
        printf("%lld\n", ans);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值