D. Not Quite Lee(裴蜀定理gcdlowbit)
Posted Lnn.
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了D. Not Quite Lee(裴蜀定理gcdlowbit)相关的知识,希望对你有一定的参考价值。
前言:思维+数论+证明给我干傻了。
题目传送门
题目类型:数论、裴蜀定理、gcd、lowbit
解析:引用一下大佬Arctic_Clam的图。设选定的子序列数组为c。
设式子左边部分为S,可以发现式子右边的xi*ci部分可以用到裴蜀定理。就是说xi * ci的和是gcd(c1…ck)的倍数。
设g = gcd(c1…ck)。若上式有解,则g|S(S也应该是g的倍数)。
注意S部分,已知g | ci,那是否有g | (ci/2)呢,有的话则直接good。
有一个简单的结论:如果x | y且x是奇数,那么x | (y/2) ;若x是偶数,则(x/2) | (y/2)。
所以g为奇数的时候,必定有g | (ci/2);而g为奇数,c中必有奇数,所以只要子序列有奇数,那就good。
沿用上面的结果,讨论偶数部分何时不good:
如果说g不能整除ci/2,用通俗的语言来说,就是ci的含2量不够高。
这里设lowbit(x)为x的二进制最低位代表的数字,例如lowbit(6) = 2。那么一定有lowbit(g) == min( lowbit(ci) )。
如果lowbit(ci) > lowbit(g)那么g|ci(ci的含2量高于g,所以除以2后还是g的倍数) ;如果lowbit(ci) = lowbit(g) ,那ci不能够单独处理,不过可以找两个相同lowbit的数加起来。推广一下就是c中lowbit(ci) = lowbit(g)的数需要偶数个(奇数个无论怎样组合都会有至少一个最低位等于g的),lowbit(ci) > lowbit(g)的随便选。
code:
#include <bits\\stdc++.h>
#define Lnnnb return 0;
#define ll long long
#define mem(a) memset(a,0,sizeof(a));
#define mod 1000000007
using namespace std;
void init();
ll n,num[35],a[202020],two[202020];
void scan()
cin >> n ;
for(ll i = 1 ; i <= n ; ++i)
cin >> a[i] ;
void solve()
ll ji = 0 , ans = 0;
for(ll i = 1 ; i <= n ; ++i)
if(a[i]%2 == 1)
ji++;
else
ll lowb = 0 , x = a[i];
while(x%2 == 0)
++lowb;
x /= 2;
num[lowb]++;
ans = (ans + (two[ji]-1) * two[n-ji]%mod) %mod; ///算上奇数的
ll res = n - ji;
for(ll i = 1 ; i <= 30 ; ++i)
res -= num[i];
///第i位为最低位,并且一定要拿
if(num[i])ans = (ans + (two[num[i]-1]-1) * two[res] %mod) %mod;
cout << ans << endl ;
int main()
two[0] = 1;
for(ll i = 1 ; i <= 200000 + 20 ; ++i)
two[i] = two[i-1]*2 %mod;
ios::sync_with_stdio(false);
///cin.tie(0);
///cout.tie(0);
ll t = 1;
///cin >> t ;
while(t--)
scan();
solve();
init();
Lnnnb
void init()
以上是关于D. Not Quite Lee(裴蜀定理gcdlowbit)的主要内容,如果未能解决你的问题,请参考以下文章