Loading

SPOJ INTSUB - Interesting Subset(数学)

http://www.spoj.com/problems/INTSUB/en/

题意:给定一个集合,该集合由1,2,3....2n组成,n是一个整数。问该集合中有趣子集的数目,答案mod1e9+7。

x的子集合有趣定义为,该子集中至少有两个数,a和b,b是a的倍数且a是集合中最小的元素。

思路:考虑集合中最小的元素a,对于每个a,使得可以构成子集的元素(即b)有beishu = 2 * n / a - 1个,那么这里只考虑这些有2^beishu - 1个。那么还剩下other = 2 * n - beishu - a个比a大的且不是a的倍数的元素,这些元素可以取或者不取,因此有2^other种。两个相乘即可以得到最小元素为a时候的子集数。

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 typedef long long LL;
 4 const int MOD = 1000000007;
 5 LL biao[2020];
 6 
 7 int main() {
 8     int t;
 9     scanf("%d", &t);
10     biao[0] = 1;
11     for(int i = 1; i <= 2000; i++) {
12         biao[i] = biao[i-1] << 1;
13         biao[i] %= MOD;
14     }
15     for(int cas = 1; cas <= t; cas++) {
16         int n;
17         scanf("%d", &n);
18         LL ans = 0;
19         for(int i = 1; i <= n; i++) {
20             int beishu = 2 * n / i - 1; // 是i的倍数的个数
21             int other = 2 * n - beishu - i; // 不是i的倍数并且大于i的个数
22             ans = biao[other] * (biao[beishu] - 1) % MOD + ans; // beishu有选和不选两种,因此是2^beishu种,因为不能全部不选,所以-1,其他的有选不选两种,是2^other
23             ans %= MOD;
24         }
25         printf("Case %d: %lld\n", cas, ans);
26     }
27     return 0;
28 }

 

posted @ 2017-03-04 10:54  Shadowdsp  阅读(194)  评论(0编辑  收藏  举报