题目描述

  Roundgod is obsessive about linear algebra. Let , everyday she will generate a binary vector randomly in . Now she wonders the probability of generating linearly independent vectors in the next days modulo . Formally, it can be proved that the answer has the form of , where and are coprime and is not a multiple of . The answer modulo thus means , where is the multiplicative inverse of .
  Wcy thinks the problem too easy. Let the answer of be , she wants to know , where denotes bitwise exclusive or operation.
  Note that when adding up two vectors, the components are modulo .

输入描述

  The input contains multiple test cases. The first line of input contains one integer , denoting the number of test cases.
  In the following lines, each line contains an integer describing one test case.

输出描述

  For each test case, output one integer indicating the answer.

示例1

输入

3
1
2
3

输出

500000004
194473671
861464136

说明

  

分析

  首先说明,向量各个维度的坐标都是在模 意义下的,基于此可以有如下性质。对于两个向量 ,这三者可视为同一向量。对于一个向量 ,若 为偶数,那么 ;若 为奇数,那么 。基于以上,两个向量 的线性组合只有 这四个向量。
   表示随机生成 个线性无关的 维向量的概率。由于要使 维向量组成的向量组线性无关,因此考虑添加第 维向量 时, 必须不属于前 个线性无关的向量构成的向量空间。接下来尝试枚举 来寻找规律。
  当 ,已有的线性无关向量组为 ;同 组成线性相关向量组的向量有 。当 ,已有的线性无关向量组为 ,那么同 构成线性相关向量组的向量有 。当 ,已有的线性无关向量组为 ,那么同 构成线性相关向量组的向量有 。基于以上,假设已经存在 个线性无关的向量 ,如果再添加一个向量 ,使得 线性相关,那么 的取值有 种;该式意味着每次在 个向量中取 个向量 ,令
  第 个向量是 维向量,必然有 种可能;但是由于已经存在 个线性无关的向量,因此其中 种取值必然会与前 个向量组成线性相关的向量组,只有 种取值是合法的。因此,第 个向量与前 个线性无关的向量组成线性无关组的概率为 。故当 时, 维向量组成线性无关组的概率 ;显然,当 时符合上式,故
  可见,,而 。因此有 ,故 。最终得到 ,已知 。预处理 的幂的逆元后,即可 得到 的值,再处理 的异或前缀和,每次查询 输出答案。

代码

/******************************************************************
Copyright: 11D_Beyonder All Rights Reserved
Author: 11D_Beyonder
Problem ID: 2020牛客暑期多校训练营(第六场) Problem B
Date: 8/26/2020
Description: Liner Algebra, Probability Theory
*******************************************************************/
#include<iostream>
#include<cstdio>
using namespace std;
typedef long long ll;
const ll mod=1000000007;
const int N=20000000;
int _;
ll f[N+2];
ll inv2[N+2];
ll ans[N+2];
int n;
void init();
ll qpow_mod(ll,ll);
int main(){
    init();
    for(cin>>_;_;_--){
        scanf("%d",&n);
        printf("%lld\n",ans[n]);
    }
    return 0;
}
void init(){
    int i;
    inv2[1]=qpow_mod(2,mod-2);
    //inv(2^n)=inv(2)^n
    for(i=2;i<=N;i++){
        inv2[i]=inv2[i-1]*inv2[1]%mod;
    }
    f[1]=inv2[1];
    for(i=2;i<=N;i++){
        f[i]=(1-inv2[i]+mod)*f[i-1]%mod;
    }
    ans[1]=f[1];
    for(i=2;i<=N;i++){
        ans[i]=f[i]^ans[i-1];
    }
}
ll qpow_mod(ll a,ll b){
    ll res=1;
    while(b){
        if(b&1){
            res=res*a%mod;
        }
        a=a*a%mod;
        b>>=1;
    }
    return res;
}