学海泛舟

spoj INTSUB - Interesting Subset 题解

原题

传送门

题目大意

一个由1,2,3……2n组成的集合,问它由多少个子集满足以下条件:该子集包含a、b,其中a是该子集中最小的元素,b是a的倍数

分析

首先考虑,显然可以枚举最小元素k(1……n),对于任意一个k,它的倍数的个数为2n/k-1,对于这些倍数,至少要取一个,那么一共有2^((2n/k-1)-1)(就是所有的可能减去一个空集的可能),剩下的元素可取可不取,那么一共有2^(2n-i-2*n/i+1),再根据乘法原理,相乘就是答案。

参考代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#include<iostream>
#include<cstring>
#include<string>
#include<algorithm>
#include<cstdio>
#include<vector>
#include<map>
using namespace std;
const int mod=1000000007;
long long f[2010];
void getf(){
f[0]=1;
for(int i=1;i<2010;++i){
f[i]=(f[i-1]<<1)%mod;
}
}
int main(){
int T;
scanf("%d",&T);
int icase=0;
getf();
while(T--){
int n;
scanf("%d",&n);
long long ans=0;
for(int i=1;i<=n;++i){
ans=(ans+(f[2*n/i-1]-1)*(f[2*n-i-2*n/i+1])%mod)%mod;
}
printf("Case %d: %lld\n",++icase,ans);
}
return 0;
}