• cdoj Dividing Numbers 乱搞记忆化搜索


    //真tm是乱搞 但是(乱搞的)思想很重要

    解:大概就是记忆化搜索,但是原数据范围太大,不可能记下所有的情况的答案,于是我们就在记下小范围内的答案,当dfs落入这个记忆范围后,就不进一步搜索,直接返回记下来的答案,这样就起到了优化的效果,但是并不知道这种复杂度是怎么算的。然而我们由大到小排序,使得状态总可以很快地落入记忆化的范围。

    dfs(n,now)代表[1..n]内不会被a[now]...a[k-1]整除的数有多少,那么答案就是dfs(n,0)。

    转移关系如下:dfs(n,now)=dfs(n,now+1)-dfs(n/a[i],now+1)

    之所以要-dfs(n/a[i],now+1)是为了避免一个数被重复减多次,能被整除的数整除后按大小排列一定是1,2,3,...,n/a[i],如果能被后面的数整除,就将其减去,也就是减dfs(n/a[i],now+1).

    /*

    某学长的讲解:

     给K个两两互素的数,问[1,N]中有多少个数不被K个数里任何一个数整除。

    假设N比较小,可以这样做。dp[i][j]表示前i个素数,范围在[1,j]里的答案。那么,方程转移dp[i][j]=dp[i-1][j]+dp[i-1][j/p[i]]。(具体为啥仔细想想素数的性质,或者按照分解素数方法来想)

    N很大,怎么办。当N<10万,20万,30万可以直接dp做。当N很大的时候,注意到j/p[i],是log级别的,情况数并不会很多。所以可以设一个M,比如M=20万,当j<=M的时候,记忆化,O(1)查询,当j>M的时候,dfs搜索。

    这题不好分析复杂度。可以发现,P数组里元素顺序是不影响答案的,我们可以把P从小到大排序,这样j/p[i]中的p[i]会更大,搜索起来更快。(当然,这只是小优化)。

    不会写的话看代码。

    */

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<cmath>
     4 #include<algorithm>
     5 #include<cstring>
     6 #include<cstdlib>
     7 #include<queue>
     8 #include<vector>
     9 #include<map>
    10 #include<stack>
    11 #include<string>
    12 
    13 using namespace std;
    14 
    15 const int MAXN=23333;
    16 
    17 long long n;
    18 int k;
    19 int a[107];
    20 long long f[MAXN][107];
    21 
    22 bool cmp(int a,int b){
    23     return a>b;
    24 }
    25 
    26 long long dfs(long long n,int now){
    27     if (now>=k || n==0) return n;
    28     if (n<MAXN && f[n][now]>=0) return f[n][now];
    29     long long tmp=dfs(n,now+1)-dfs(n/a[now],now+1);
    30     if (n<MAXN) f[n][now]=tmp;
    31     return tmp;
    32 }
    33 
    34 int main(){
    35     scanf("%lld%d",&n,&k);
    36     for (int i=0;i<MAXN;i++){
    37             for (int j=0;j<k;j++){
    38                     f[i][j]=-1;
    39             }
    40     }
    41     for (int i=0;i<k;i++) scanf("%d",&a[i]);
    42     sort(a,a+k,cmp);
    43     printf("%lld
    ",dfs(n,0)); //printf("I64d printed
    ");
    44     return 0;
    45 }
    46 /*
    47 20 3
    48 2 3 5
    49 
    50 50 2
    51 15 8
    52 */
    View Code
  • 相关阅读:
    无法重用Linq2Entity Query
    The Joel Test
    MSBuilder directly instead of default VSComplie with keyborad shotcut 原创
    客户端缓存(Client Cache)
    关于代码重构和UT的一些想法,求砖头
    ExtJS2.0实用简明教程 应用ExtJS
    Perl information,doc,module document and FAQ.
    使用 ConTest 进行多线程单元测试 为什么并行测试很困难以及如何使用 ConTest 辅助测试
    史上最简单的Hibernate入门简介
    汽车常识全面介绍 传动系统
  • 原文地址:https://www.cnblogs.com/baby-mouse/p/4542011.html
Copyright © 2020-2023  润新知