Java

Owll 发表于 1年前 · 关联问题 A⊕B 问题

题目:A⊕B 问题

思路:

  1. 1⊕0=1,0⊕1=1,1⊕1=0,0⊕0=0
  2. 对于数中的某一位,如果对答案产生影响,那么该位必然和x中对应的位的值相反。从x出发,如果x的第i位为1,那么只有第i位为0且小于等于n的数才能算入答案,同理x的第i位为0,那么数的第i位为1。且答案ans=ans+2^i
  3. 因此,可以统计0~n中第i位为1和为0的数量,然后根据x中的对应位取相反的值的数量*2^i计入答案。

代码如下:

import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.io.PrintWriter; public class Main { //快速输入 static BufferedReader br=new BufferedReader(new InputStreamReader(System.in)); //快速输出 static PrintWriter pw=new PrintWriter(new OutputStreamWriter(System.out)); static int mod=1_000_000_007; public static void main(String[] args) throws IOException { String[] s=br.readLine().split(" "); String n=Long.toBinaryString(Long.parseLong(s[0])); String x=Long.toBinaryString(Long.parseLong(s[1])); int a=n.length(),b=x.length(); //将n和x的二进制长度增长到一样的长度 if(a<b) { for(int i=0;i<b-a;i++) { n='0'+n; } } else { for(int i=0;i<a-b;i++) { x='0'+x; } } int m=n.length(); char[] c=n.toCharArray(); long pre=1; long[][] cnt=new long[m][2]; //计算第i位的数量,左边不取最大值,右边取任意值 for(int i=m-1;i>0;i--) { long tmp=Long.parseLong(n.substring(0, i),2)%mod*pre%mod; cnt[i][0]=tmp; cnt[i][1]=tmp; pre=pre*2%mod; } pre=1; //左边取最大值,右边取任意值 for(int i=m-1;i>=0;i--) { if(i==m-1) { for(int j=0;j<m;j++) { cnt[j][c[j]-'0']=(cnt[j][c[j]-'0']+pre)%mod; } } if(c[i]=='1') { for(int j=0;j<i;j++) { cnt[j][c[j]-'0']=(cnt[j][c[j]-'0']+pre)%mod; } cnt[i][0]=(cnt[i][0]+pre)%mod; } pre=pre*2%mod; } char[] cx=x.toCharArray(); int len=cx.length; long ans=0; pre=1; //计算每一位的贡献值 for(int i=len-1;i>=0;i--) { if(cx[i]=='0') { ans=(ans+cnt[i][1]*pre%mod)%mod; } else { ans=(ans+cnt[i][0]*pre%mod)%mod; } pre=pre*2%mod; } pw.println(ans); pw.flush(); } }

ABCC 发表于 1年前

oo大佬太强啦!!