2019 China Collegiate Programming Contest Final (CCPC-Final 2019) L. Lottery(二进制)
Posted issue是fw
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2019 China Collegiate Programming Contest Final (CCPC-Final 2019) L. Lottery(二进制)相关的知识,希望对你有一定的参考价值。
考虑现在有 x i x_i xi个 2 a i 2^{a_i} 2ai
因为 x i < = 1 0 9 x_i<=10^9 xi<=109,所以即使把这部分全选上最多也就影响到第 a i + 30 a_i+30 ai+30位二进制
至于第 a i + 31 a_i+31 ai+31往后的二进制怎么选,已经和前面完全没有关系,可以用乘法原理计数
设我们已经知道第 [ l , r ] [l,r] [l,r]位二进制是连续的,也就是第 l l l位二进制最多可以影响到第 r r r位
这段有多少方案呢??
累加 s u m = ∑ b i ∈ [ l , r ] 2 b i − l ∗ x i sum=\\sum\\limits_{b_i\\in[l,r]} 2^{b_i-l}*x_i sum=bi∈[l,r]∑2bi−l∗xi
我们把第 l l l位二进制当作第 0 0 0位二进制,那么 [ 0 , s u m ] [0,sum] [0,sum]所有数都可以凑出来
所以这个连续段的方案数为 s u m sum sum
乘起来即可
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int mod = 1e9+7;
const int maxn = 2e5+10;
int t,n,casenum;
struct p
{
int a,x;
bool operator < ( const p&tmp ) const
{
return a<tmp.a;
}
}a[maxn];
int quick(int x,int n)
{
int ans = 1;
for( ; n ; n>>=1,x=x*x%mod )
if( n&1 ) ans = ans*x%mod;
return ans;
}
signed main()
{
cin >> t;
while( t-- )
{
cin >> n ;
for(int i=1;i<=n;i++) cin >> a[i].a >> a[i].x;
sort( a+1,a+1+n );
int ans = 1, now=0, l = a[1].a, temp = a[1].x;
for(int i=1;i<=n;i++)
{
now = ( now+quick(2,a[i].a-l )*a[i].x%mod )%mod;//总共1的个数
if( i!=n && a[i+1].a-a[i].a<=30 && (temp>>(a[i+1].a-a[i].a) ) )
{
temp = a[i+1].x+( temp>>(a[i+1].a-a[i].a) );
continue;
}
ans = ans*(now+1)%mod;
now = 0, l = a[i+1].a, temp = a[i+1].x;
}
printf("Case #%d: ",++casenum);
cout << ans << endl;
}
}
以上是关于2019 China Collegiate Programming Contest Final (CCPC-Final 2019) L. Lottery(二进制)的主要内容,如果未能解决你的问题,请参考以下文章