Given a directed graph with n 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 Format
Multiple test cases (no more than 10000).
In each test case, one integer in a line denotes n(2≤n≤1018).
Output Format
Output the maximum flow modulo 1000000007 for each test case.
样例输入
2
样例输出
1
题目来源
设点的最大编号为n,则n二进制最高位是1,设另一个数m对应的二进制位是0,则n^m>0^m=m,0到m的所有流量必定可以到达汇点n.这一部分的贡献是2^x*(2^x-1)/2, 2^x是小于等于n的最大的2的次方。
对于二进制最高位和n相同的数字k,可以转达的最大流量就是n^k.因为n^k<0^k=k.那么我们只要计算这一部分的异或和就可以了。
那么异或打个表找规律,发现把n转为二进制之后,除去最高位,每一位对答案的贡献是1,5,22,92......,这一串数字可以通过递推:
sum=q=1
for ()
sum=sum*2-q;
q=q*4;
sum+=q;
得到。
之后就直接上java的BigInteger.
package main;
import java.math.BigInteger;
import java.util.Scanner;
public class Fuck {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
while (in.hasNext()) {
BigInteger n;
BigInteger p[]=new BigInteger [105];
BigInteger a[]=new BigInteger [105];
BigInteger b[]=new BigInteger [105];
BigInteger c[]=new BigInteger [105];
BigInteger q=BigInteger.ONE,sum=BigInteger.ONE,m=BigInteger.valueOf(1000000007);
int i;
p[0]=BigInteger.ZERO;a[0]=BigInteger.ONE;b[0]=BigInteger.ONE;
for (i=1;i<=64;i++) {
p[i]=sum;
sum=sum.add(sum).subtract(q);
q=q.multiply(BigInteger.valueOf(4));
sum=sum.add(q);
}
for (i=1;i<=61;i++) {
a[i]=a[i-1].multiply(BigInteger.valueOf(2));
b[i]=a[i].multiply(a[i].subtract(BigInteger.ONE)).divide(BigInteger.valueOf(2));
}
while (in.hasNextBigInteger()) {
n=in.nextBigInteger();
if (n.compareTo(BigInteger.valueOf(2))==0) {
System.out.println("1");
continue;
}
n=n.subtract(BigInteger.ONE);
int cnt=1;
while (n.compareTo(a[cnt+1])>=0) cnt++;
BigInteger ans=b[cnt];
ans=ans.add(n);
n=n.subtract(a[cnt]);
cnt=0;
while (n.compareTo(BigInteger.ZERO)!=0) {
cnt++;
if (n.mod(BigInteger.valueOf(2)).compareTo(BigInteger.ONE)==0) ans=ans.add(p[cnt]);
n=n.divide(BigInteger.valueOf(2));
}
ans=ans.mod(m);
System.out.println(ans);
}
}
}
}