您的位置:首页 > 理论基础 > 计算机网络

Maximum Flow - 2017 ACM-ICPC 亚洲区(西安赛区)网络赛

2017-09-16 23:01 363 查看
Given a directed graph with nn nodes,
labeled 0,1,
\cdots, n-10,1,⋯,n−1.
For each <i,
j><i,j> satisfies 0
\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 ii xor jj.

Find the maximum flow network from the 0-th node to the (n-1)-th node, modulo 10000000071000000007.

Input Format

Multiple test cases (no more than 1000010000).

In each test case, one integer in a line denotes n(2
\le n \le 10^{18})n(2≤n≤10​18
4000
​​).

Output Format

Output the maximum flow modulo 10000000071000000007 for
each test case.

样例输入

2


样例输出

1



题目来源

2017
ACM-ICPC 亚洲区(西安赛区)网络赛

设点的最大编号为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);
}
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: