zoukankan      html  css  js  c++  java
  • hdu4935 Prime Tree(2014多校联合第七场)

    首先这是一道dp题,对题意的把握和对状态的处理是解题关键。

    题目给出的范围是n在1到1e11之间,由于在裂变过称中左儿子总是父亲节点的一个非平凡约数,容易看出裂变过程只与

    素数幂有关,并且显然有素数不超过11个,幂指数不超过40,实际上可以用一个大小为11的数组来等价地表示状态,状态

    与其内元素顺序无关,因此可以排序,压缩后的状态不超过3000个(准确地说是2957个,通过一个简单的dfs即可统计出此结果)。

    以上解决了题目的规模问题。

    这道题目我开始因为理解错题意wa了几次,不能通过统计儿子节点的期望高度的平均值再加1得到以父节点为根的数的期望高度,因为两颗子树

    的高度在概率上对根树的影响不是相互独立的。

    可以设dp(i, j)为以状态i为根深度为j的概率:

    那么显然有dp(i, j) = sigma(dp(k, j - 1) * sigma(i / k, t) + sigma(k, t) * dp(i / k, j - 1) + dp(k, j - 1) * dp(i / k, j -1)) / (N - 2)

    其中k | i, 且 k ≠ 1,k≠ i, t < j - 1。

    以状态i为根的树的期望高度:exp(i) = sigma(j * dp(i, j)), 0 < j < 40.

    因此状态转移可以通过枚举左儿子得到,整体复杂度O(3000 * 3000 * 40)。

      1 #include <cstdio>
      2 #include <cstring>
      3 #include <algorithm>
      4 #include <map>
      5 #include <string>
      6 #include <vector>
      7 #include <set>
      8 #include <cmath>
      9 #include <ctime>
     10 #include <cassert>
     11 #pragma comment(linker, "/STACK:102400000,102400000")
     12 #define lson (u << 1)
     13 #define rson (u << 1 | 1)
     14 #define cls(i, j) memset(i, j, sizeof i)
     15 using namespace std;
     16 typedef __int64 ll;
     17 const double eps = 1e-6;
     18 const double pi = acos(-1.0);
     19 const int maxn = 1e5 + 10;
     20 const int maxm = 1050;
     21 const int inf = 0x3f3f3f3f;
     22 const ll linf = 0x3fffffffffffffff;
     23 const ll mod = 1e9 + 7;
     24 
     25 int debug = 0;
     26 map<ll, int> mapi;
     27 int buf[11], k1;
     28 ll S = (ll)1e11;
     29 double dp[3000][40];
     30 
     31 int a[] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31};
     32 bool cmp(int a, int b) { return a > b; }
     33 int prime[maxn], k;
     34 bool vis[3000];
     35 
     36 ll Hash(int *t){
     37     ll tem = 1, ans = 0;
     38     for(int i = 0; i < 11; i++){
     39         ans += tem * t[i];
     40         tem *= 37;
     41     }
     42     return ans;
     43 }
     44 
     45 int stack[11], k2;
     46 ll states[3000];
     47 int ks;
     48 int table[3500][11];
     49 
     50 void dfs(ll num, int limit, int next){
     51     if(next){
     52         memcpy(buf, stack, sizeof buf);
     53         sort(buf, buf + 11, cmp);
     54         ll hash_value = Hash(buf);
     55         states[ks++] = hash_value;
     56         memcpy(table[ks - 1], buf, sizeof buf);
     57         mapi[hash_value] = ks - 1;
     58     }
     59     if(next > 10) return;
     60     for(int i = 1; i <= limit; i++){
     61         num *= a[next];
     62         if(num > S) break;
     63         stack[k2++] = i;
     64         dfs(num, i, next + 1);
     65         stack[--k2] = 0;
     66     }
     67 }
     68 
     69 void shaffix(){
     70     bool vis[500000 + 10];
     71     int mid = (int)5e5 + 10;
     72     cls(vis, 0);
     73     for(int i = 2; i < mid; i++){
     74         if(vis[i]) continue;
     75         prime[k++] = i;
     76         for(ll j = (ll)i * 2; j < mid; j += i) vis[j] = 1;
     77     }
     78 }
     79 
     80 void cal(int id);
     81 
     82 void dfs1(int id, int next){
     83     if(next > 10){
     84         int buf1[11], buf2[11];
     85         memcpy(buf1, stack, sizeof stack);
     86         for(int i = 0; i < 11; i++) buf2[i] = table[id][i] - buf1[i];
     87         sort(buf1, buf1 + 11, cmp);
     88         sort(buf2, buf2 + 11, cmp);
     89         if(!buf1[0] || !buf2[0]) return;
     90         ll hash_value1 = Hash(buf1), hash_value2 = Hash(buf2);
     91         int id1 = mapi[hash_value1], id2 = mapi[hash_value2];
     92         cal(id1), cal(id2);
     93         double prefix_left = 0, prefix_right = 0;
     94         for(int i = 0; i < 39; i++){
     95             dp[id][i + 1] += dp[id1][i] * prefix_right +
     96             prefix_left * dp[id2][i] + dp[id1][i] * dp[id2][i];
     97             prefix_left += dp[id1][i], prefix_right += dp[id2][i];
     98         }
     99         return;
    100     }
    101     for(int i = 0; i <= table[id][next]; i++){
    102         stack[k2++] = i;
    103         dfs1(id, next + 1);
    104         stack[--k2] = 0;
    105     }
    106 }
    107 
    108 void cal(int id){
    109     if(vis[id]) return;
    110     k2 = 0;
    111     dfs1(id, 0);
    112     int sum = 1;
    113     for(int i = 0; i < 11; i++) sum *= 1 + table[id][i];
    114     sum -= 2;
    115     for(int i = 1; i < 40; i++) dp[id][i] /= sum;
    116     vis[id] = 1;
    117     //printf("%d+
    ", id);
    118 }
    119 
    120 void init(){
    121     shaffix();
    122     cls(vis, 0);
    123     vis[0] = 1;
    124     mapi.clear();
    125     //0...10 < 10^11
    126     cls(stack, 0);
    127     ks = k2 = 0;
    128     dfs(1, 40, 0);
    129     cls(dp, 0);
    130     dp[0][1] = 1;
    131     for(int i = 1; i < ks; i++) cal(i);
    132 }
    133 
    134 double solve(ll num){
    135     cls(buf, 0);
    136     k1 = 0;
    137     int mid = (int)sqrt((double)num);
    138     for(int i = 0; i < k && prime[i] <= mid; i++){
    139         if(num % prime[i]) continue;
    140         while(num % prime[i] == 0) ++buf[k1], num /= prime[i];
    141         mid = (int)sqrt((double)num);
    142         k1++;
    143     }
    144     if(num != 1) buf[k1++] = 1;
    145     sort(buf, buf + 11, cmp);
    146     ll hash_value = Hash(buf);
    147     double ans = 0;
    148     int id = mapi[hash_value];
    149     for(int i = 1; i < 40; i++) ans += dp[id][i] * i;
    150     return ans;
    151 }
    152 
    153 int main(){
    154     //freopen("in.txt", "r", stdin);
    155     //freopen("out.txt", "w", stdout);
    156     int T, kase = 0;
    157     init();
    158     scanf("%d", &T);
    159     ll n;
    160     while(T--){
    161         scanf("%I64d", &n);
    162         double ans = solve(n);
    163         printf("Case #%d: %.6f
    ", ++kase, ans);
    164     }
    165     return 0;
    166 }
    View Code
  • 相关阅读:
    Leetcode Binary Tree Preorder Traversal
    Leetcode Minimum Depth of Binary Tree
    Leetcode 148. Sort List
    Leetcode 61. Rotate List
    Leetcode 86. Partition List
    Leetcode 21. Merge Two Sorted Lists
    Leetcode 143. Reorder List
    J2EE项目应用开发过程中的易错点
    JNDI初认识
    奔腾的代码
  • 原文地址:https://www.cnblogs.com/astoninfer/p/4947470.html
Copyright © 2011-2022 走看看