Problem Description
Given a directed graph with nn nodes, labeled 0,1,⋯,n−1.
For each <i, j> satisfies 0≤i<j<n, there exists an edge from the i-th node to the j-th node, the capacity of which is i xor j.
Find the maximum flow network from the 0-th node to the (n-1)-th node, modulo 1000000007.
Input
Multiple test cases (no more than 10000).
In each test case, one integer in a line denotes n(2≤n≤10^18 ).
Output
Output the maximum flow modulo 11000000007 for each test case.
Sample Input
2
Sample Output
1
题意:多组数据,每组给出一个数 n,代表有 n 个编号从 0 到 n-1 的点,现在对于这 n 个点,当 i<j 时,两点之间存在一条边,其边容量为 i^j,问从 0 到 n-1 的最大流
思路:
多画几组样例可以发现,0 到 n-1 两点之间必须要割
对于任意一个 i,0 到 i 与 i 到 n−1 至少要割一个,因此考虑 i 在 n−1 的最高位是否为 0 即可,若最高位为 0 就割 0 到 i,否则就割 i 到 n−1
在图中经过这样的割后,一定存在一个分界线 100...00,使得前面所有的点与 n-1 连通不与 0 连通,后面所有的点与 0 连通不与 n-1 连通,这样 0 与 n-1 就隔开了
于是问题就转换成了求割下来的各条边的流量和,从 i 个最高位考虑:
若 i 的最高位为 0 时,割为 0 到 i,其流量和就是 1+2+...+(2^(len-1)-1)
当 i 的最高位为 1 时,割为 i 到 n−1,考虑从低位向高位找 n−1 中除最高位外为 1 的位,设当前为第 j 位,那么可对从最高位到第 j+1 位与 n-1 相同且第 j 位为 0 的数求和
对于这些数,j-1 位到 0 位于 n-1 的异或值就是 1+2+...+(2^(j-1)-1),第 j 位与 n-1 的异或值为 2^j,最高位到第 j+1 位与 n-1 的异或值为 0
Source Program
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<string>
#include<cstring>
#include<cmath>
#include<ctime>
#include<algorithm>
#include<utility>
#include<stack>
#include<queue>
#include<vector>
#include<set>
#include<map>
#include<bitset>
#define PI acos(-1.0)
#define INF 0x3f3f3f3f
#define LL long long
#define Pair pair<int,int>
LL quickPow(LL a,LL b){ LL res=1; while(b){if(b&1)res*=a; a*=a; b>>=1;} return res; }
LL quickModPow(LL a,LL b,LL mod){ LL res=1; a=a%mod; while(b){if(b&1)res=(a*res)%mod; a=(a*a)%mod; b>>=1;} return res; }
LL getInv(LL a,LL mod){ return quickModPow(a,mod-2,mod); } // (a/b)%MOD=(a%MOD * getInv(b)%MOD)%MOD
const double EPS = 1E-10;
const int MOD = 1E9+7;
const int N = 100000+5;
const int dx[] = {-1,1,0,0,-1,-1,1,1};
const int dy[] = {0,0,-1,1,-1,1,-1,1};
using namespace std;
int main() {
LL n;
while(scanf("%lld",&n)!=EOF){
if(n==2)
printf("1\n");
else{
n--;
LL temp=n;
int len=0;
while(temp){
len++;
temp/=2;
}
LL temp1=quickModPow(2,len-2,MOD);
LL temp2=(quickModPow(2,len-1,MOD)-1+MOD)%MOD;
LL res=(temp1%MOD*temp2%MOD)%MOD;
res=(res+n)%MOD;
for(int i=0; i<len-1; i++) {
if(n&(1LL<<i)) {//最高位为1时
if (i==0)
res=(res+1)%MOD;
else{
temp1=((3LL<<i)%MOD-1+MOD)%MOD;
temp2=quickModPow(2,i-1,MOD);
res=(res+(temp1*temp2)%MOD)%MOD;
}
}
}
printf("%lld\n", res);
}
}
return 0;
}