题目链接
题意
有 n n n 个盒子,每个盒子里面有 x [ i ] x[i] x[i] 个球, 每个球的权值为 2 a [ i ] 2^{a[i]} 2a[i], 你可以在任意个盒子中取任意个球, 求所有球的 s u m sum sum 共能组成多少种数字.
思路
很显然,每个盒子上的权值对应了一个二进制位,多拿一个球就对应于以第
a
[
i
]
a[i]
a[i] 位为起始位的二进制的
+
1
+1
+1, 所以,对每一个盒子的
a
[
i
]
a[i]
a[i] 排序一下,从小到大枚举,每个互相影响不到的盒子可以分开来考虑,最后的结果相乘即可。在可以影响到的盒子之间,他们的二进制是这种情况:
可以把它看成是一个数字,计算该数字最大是多少就好了。
代码
#include<bits/stdc++.h>
#define endl "\n"
#define int long long
#define x first
#define y second
using namespace std;
typedef long long ll;
const int N = 1e5 + 10, mod = 1e9 + 7, inf = 1e9;
const double eps = 1e-7;
int n, test = 1;
struct node{
int x, k;
}a[N];
bool cmp(node a, node b){
return a.k < b.k;
}
void solve()
{
cout << "Case #" << test ++ << ": ";
cin >> n;
for(int i = 1; i <= n; i ++) cin >> a[i].k >> a[i].x;
sort(a + 1, a + 1 + n, cmp);
int ans = 1;
for(int i = 1; i <= n; i ++){
int sx = a[i].x, p = a[i].k, val = 0, base = 1;
while(sx){
val = (val + (base * (sx & 1)) % mod) % mod;
sx >>= 1, p ++, base = base * 2 % mod;
if(!sx) break;
if(a[i + 1].k == p) sx += a[i + 1].x, i ++;
}
ans = ans * (val + 1) % mod;
}
cout << ans << endl;
}
signed main(){
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
int t = 1;
cin >> t;
while(t --) solve();
return 0;
}