D. Not Quite Lee

发布时间 2023-03-28 09:23:28作者: basicecho

思路

对于偶数,可以采用裴蜀定理确定为是中间的奇数的数量,并且数量是占一半的。所以只需要先确定最小的gcd,然后大的任选,就可以求出这个gcd中不满足条件的数量的个数。
采用固定gcd,从而求解就可以了。

又是和二进制有关,并且配上了申请的裴蜀定理。

代码

/*
数论菜鸡

连续的整数进行组成
所有的序列和都是0,长度是bi

只要有奇数,随便怎么样都是可以的
考虑全部是偶数的序列就可以了
长度相同可以,长度不同也是可能可以的

每一次移动,变化的数值是移动的,sum(bi)=bi/2 + kbi k为任意整数
则(a1+a2+a3......)/2 = ka1 + ka2 + ka3 ......

也就是只需要(a1+a2+a3)除去gcd后,奇数的个数为偶数就可以了
这里采用减去的方法
选奇数的个数的方案数量有一半的数量

比他大的任意取就可以了

求和+裴蜀定理
化简数组中gcd的数量

数学还是不是特别擅长呀
*/
#include <bits/stdc++.h>
using namespace std;
const int M = 1e6 + 5;
#define endl '\n'
#define int long long
using pii = pair<int, int>;
const int mod=1e9+7;

int kpow(int a,int b) {
    int ans=1;
    while(b) {
        if(b&1)ans=ans*a%mod;
        b>>=1;
        a=a*a%mod;
    }
    return ans;
}

int num[50];
void solve() {
    int n;cin>>n;
    for(int i=1,x;i<=n;i++) {
        cin>>x;
        int cnt=0;
        while(x%2==0)x/=2,cnt++;
        num[cnt]++;
    }//统计数的数量
    int sum=0;
    for(int i=1;i<=32;i++)
        if(num[i]) {//保证gcd为这个数
            int tmp=kpow(2,num[i]-1);
            for(int j=i+1;j<=32;j++)
                tmp=tmp*kpow(2,num[j])%mod;//比他大的都是不增加贡献的
            sum=(sum+tmp)%mod;
        }
    cout<<(kpow(2,n)-1-sum+mod)%mod<<endl;
}

signed main() {
    ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
    solve();
    return 0;
}