zoukankan      html  css  js  c++  java
  • 2016_1_17_第二题

    这道题调了大概一个多小时终于过了,有许多地方我希望记清楚,我还是记下来。

    先给上代码

     1 #include <cstdio>
     2 #include <iostream>
     3 #include <cstring>
     4 #include <cstdlib>
     5 #include <cmath>
     6 using namespace std;
     7 const int N = 3003;
     8 int n;
     9 int prime[N],pd,t,record[N];
    10 bool vis[N];
    11 int small[N],ts,tot;
    12 int big[N],tb;
    13 int biao[603][1003],size[1003];
    14 long long dp[(1<<16)+10][603];
    15 void dfs(int i,int linshi,int t,long long kk) {
    16     if(t > ts) return;
    17     if(kk*small[t]<=n) {
    18         biao[i][++size[i]] = linshi+(1<<(t-1));
    19         dfs(i,linshi+(1<<(t-1)),t+1,kk*small[t]);
    20         dfs(i,linshi,t+1,kk);
    21     }
    22 }
    23 inline void solve(int n) {
    24     int k;
    25     for(int s = 2 ; s <= n ; ++s) {
    26         if(!vis[s]) prime[++t] = s;
    27         for(int j = 1 ; j <= t && (k=prime[j]*s)<=n ; ++j) {
    28             vis[k] = true;
    29             if(s%prime[j]==0) break;
    30         }
    31     }
    32     for(int i = 1 ; i <= n ; ++i) {
    33         int linshi = i;
    34         for(int j = 1 ; j <= t && linshi!=1 ; ++j) {
    35             while(linshi%prime[j]==0 && linshi!=1) {
    36                 linshi/=prime[j];
    37                 record[prime[j]]++;
    38             }
    39         }
    40     }
    41     pd = sqrt(n);
    42     for(int i = 1 ; i <= n ; ++i) {
    43         if(record[i]%2==1) {
    44             if(i<pd) small[++ts] = i;
    45             else big[++tb] = i;
    46         }
    47     }
    48     tot = ts+tb;
    49     for(int i = 1 ; i <= ts ; ++i) dfs(i,(1<<(i-1)),i+1,small[i]),biao[i][++size[i]] = (1<<(i-1));
    50     for(int i = 1 ; i <= tb ; ++i) dfs(i+ts,0,1,big[i]);
    51     int end = (1<<ts)-1;
    52     dp[end][1] = 1;
    53     for(int i = 1 ; i <= tot ; ++i) {
    54         for(int j = 0 ; j <= end ; ++j) {
    55             if(dp[j][i]==0) continue;
    56             dp[j][i+1] = dp[j][i];
    57             for(int k = 1 ; k <= size[i] ; ++k)
    58                 if((biao[i][k]&j)==biao[i][k]) dp[j-biao[i][k]][i+1] += dp[j][i];
    59         }
    60     }
    61     printf("%lld",dp[0][tot]*2);
    62 }
    63 int main() {
    64     freopen("test.in","r",stdin);
    65     freopen("test.out","w",stdout);
    66     scanf("%d",&n);
    67     solve(n);
    68 }
    View Code

    首先感觉那个DFS是可以直接做的,就是可以直接转移的,当时受了同学的蛊惑我于是打了个转移表。反正还是蛮优的,然后这道题重点就是DP了,最开始我只想考虑大质数的时候是可能有问题的。所以我把小质数加上来一起搞,可以处理出只选大质数的时候的方案。代码还是可以好好感受感受在最后一步J到大质数J+1的时候,我就可以知道集合s为各个状态时I的方案,然后就可以累加起来咯。

    隔两天再看看,别忘了蛤蛤!

  • 相关阅读:
    android 限定符参考
    Fragment生命周期
    碎片和活动之间通信
    Fragment碎片的使用
    使用Intent传值及回传值
    Calendar 获取年 月 日 时 分 秒
    Python函数:2018-07-30
    Python 字符串 2018-07-27
    Python 异常 2018-08-01
    __future__ 模块 2018-08-09
  • 原文地址:https://www.cnblogs.com/registerzxr/p/5149017.html
Copyright © 2011-2022 走看看