Given a directed graph with nnn nodes, labeled 0,1,⋯,n−10,1, \cdots, n-10,1,⋯,n−1.
For each <i,j><i, j><i,j> satisfies 0≤i<j<n0 \le i < j < n0≤i<j<n, there exists an edge from the i-th node to the j-th node, the capacity of which is iii xor jjj.
Find the maximum flow network from the 0-th node to the (n-1)-th node, modulo 100000000710000000071000000007.
Input Format
Multiple test cases (no more than 100001000010000).
In each test case, one integer in a line denotes n(2≤n≤1018)n(2 \le n \le 10^{18})n(2≤n≤1018).
Output Format
Output the maximum flow modulo 100000000710000000071000000007 for each test case.
样例输入
2
样例输出
1
分析:不是很懂各位打表找规律选手,最优方案应该是0连向每一个点,然后每一个点再直接连向最后一个点,考虑此时的最大流,设n-1的最高位为2^k,则1到2^k-1 异或上n-1一定是大于自己的,所以这部分流量可以直接算一个等差数列和求出来,然后考虑大于2^k的点,这些点能贡献给n-1的流量一定是其编号和n-1的异或,我们去掉一定会被异或掉的最高位k后就变成了sigma(i ^ n) 其中 i <= n,这部分和手动推一下也可以直接计算。
#include <bits/stdc++.h>
const int MOD = 1000000007;
using namespace std;
typedef unsigned long long ll;
ll n;
ll ksm(ll x,ll y)
{
ll cnt = 1;
while(y)
{
if(y & 1) cnt = cnt * x % MOD;
x = x * x % MOD;
y>>=1;
}
return cnt;
}
int main()
{
while(scanf("%llu",&n) != EOF)
{
n--;
ll ans = 0;
bool flag = false;
for(int i = 63;i >= 0;i--)
{
if( (1ll<<i) & n)
{
if(!flag)
{
flag = true;
ans = (ans + ((1ll<<(i-1)) % MOD)*( ((1ll<<i) - 1) % MOD) % MOD) % MOD;
}
else
ans = (ans + ksm(2,2*i) + ((1ll<<(i-1)) % MOD) * ( ((1ll<<i) - 1) % MOD) % MOD) % MOD;
}
}
cout<<(ans+n) % MOD<<endl;
}
}