首页 > 其他 > 详细

第四周 3.20-3.26

时间:2016-03-21 23:01:27      阅读:244      评论:0      收藏:0      [点我收藏+]

3.20

HDU 5647 DZY Loves Connecting

不能直接逆元搞,因为可能会变成0。(据说可以特判一下。

然而直接dp[0]子树方案数,dp[1]子树贡献一次dp就可以了。

考虑当前节点新加一个孩子树,增加的贡献分两部分,

一部分是原来树节点的贡献,增加原来的答案×新增孩子树方案数,

另一部分是新增孩子树的贡献,增加原来方案数×新增孩子树答案。

技术分享
 1 #pragma comment(linker, "/STACK:102400000,102400000")
 2 #include <iostream>
 3 #include <cstdio>
 4 #include <cstring>
 5 #include <algorithm>
 6 using namespace std;
 7 typedef long long LL;
 8 const LL mod = 1e9 + 7;
 9 const int maxn = 2e5 + 10;
10 
11 // tree
12 int cnt, h[maxn];
13 struct edge
14 {
15     int to, pre;
16 } e[maxn<<1];
17 
18 void add(int from, int to)
19 {
20     cnt++;
21     e[cnt].pre = h[from];
22     e[cnt].to = to;
23     h[from] = cnt;
24 }
25 
26 void init()
27 {
28     cnt = 0;
29     memset(h, 0, sizeof(h));
30 }
31 
32 // dp
33 LL dp[maxn][2];
34 void dfs(int x, int f)
35 {
36     dp[x][0] = dp[x][1] = 1;
37     for(int i = h[x]; i; i = e[i].pre)
38     {
39         int to = e[i].to;
40         if(to == f) continue;
41         dfs(to, x);
42         dp[x][1] = (dp[x][1] * (dp[to][0] + 1) + dp[x][0] * dp[to][1]) % mod;
43         dp[x][0] = dp[x][0] * (dp[to][0] + 1) % mod;
44     }
45 }
46 
47 int main(void)
48 {
49     int T;
50     scanf("%d", &T);
51     while(T--)
52     {
53         init();
54         int n;
55         scanf("%d", &n);
56         for(int i = 2; i <= n; i++)
57         {
58             int p;
59             scanf("%d", &p);
60             add(i, p), add(p, i);
61         }
62         dfs(1, 0);
63         LL ans = 0;
64         for(int i = 1; i <= n; i++) ans = (ans + dp[i][1]) % mod;
65         printf("%I64d\n", ans);
66     }
67     return 0;
68 }
Aguin

 

HDU 5648 DZY Loves Math

预处理每个数的子集( 关于j = (j - 1) & i 这个飘逸写法我果然不是最后一个知道的- -。

枚举每对a = i & j, b = i | j,那么a就是i和j公用的bit,接下来任务就是把剩下的bit(即b - a)分配给i和j。

考虑把bit分给i,下界是b - m,小于这个值j就会大于m炸掉,上界是n - a,否则i爆掉。

然后在b - a的子集里面二分找上下界之间的个数就好了。

具体过程就是这样,但是要注意如果公共部分是0,两边至少都分配一个bit,因为i,j要正数。

技术分享
 1 #include <iostream>
 2 #include <cstdio>
 3 #include <vector>
 4 #include <algorithm>
 5 using namespace std;
 6 typedef long long LL;
 7 const int maxn = 1 << 16;
 8 vector<int> A[maxn];
 9 int n, m, len;
10 LL ans;
11 
12 int gcd(int a, int b)
13 {
14     if(!b) return a;
15     return a % b ? gcd(b, a % b) : b;
16 }
17 
18 int get(int left, int x)
19 {
20     if(x < 0) return 0;
21     int l = 0, r = A[left].size() - 1, mid;
22     while(l < r)
23     {
24         mid = r - (r - l) / 2;
25         if(A[left][mid] <= x) l = mid;
26         else r = mid - 1;
27     }
28     return l + 1;
29 }
30 
31 void dfs(int a, int b, int d)
32 {
33     if(d == len)
34     {
35         int left = b - a, l = left + a - m, r = n - a;
36         if(!a) r = min(r, left - 1), l = max(l, 1);
37         if(l > r) return;
38 //        printf("a = %d , b = %d, gcd = %d, cnt = %d\n", a, b, gcd(a,b), get(left, r) - get(left, l - 1));
39         ans += (LL) gcd(a, b) * (get(left, r) - get(left, l - 1));
40         return;
41     }
42     dfs(a + (1 << d), b + (1 << d), d + 1);
43     dfs(a, b + (1 << d), d + 1);
44     dfs(a, b, d + 1);
45 }
46 
47 int main(void)
48 {
49     for(int i = 0; i < maxn; i++)
50     {
51         for(int j = i; ; j = (j - 1) & i)
52         {
53             A[i].push_back(j);
54             if(!j) break;
55         }
56         reverse(A[i].begin(), A[i].end());
57     }
58     int T;
59     scanf("%d", &T);
60     while(T--)
61     {
62         scanf("%d %d", &n, &m);
63         if(n < m) swap(n, m);
64         len = 0;
65         while((1 << len) <= n) len++;
66         ans = 0;
67         dfs(0, 0, 0);
68         printf("%I64d\n", ans);
69     }
70     return 0;
71 }
Aguin

 

第四周 3.20-3.26

原文:http://www.cnblogs.com/Aguin/p/5304188.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!