zoukankan      html  css  js  c++  java
  • NC17065-子序列-(数学+dp)

    https://ac.nowcoder.com/acm/problem/17065

    题意:有n个数的数组a,求数组的子序列个数,满足子序列 { ap1,ap2,...apm },p1<p2...<pm,使得子序列中的任意两个数满足ai< aji (i<j)。结果对1e9+7求模。

    思路:看起来吓死人,对不等式一步步化简。

    ai< aji 

    → log ai< log aji

    → j*log ai < i*log aj

    → (log ai)/i <  (log aj)/j

    对于每一个数ai可以处理出一个(log ai)/i的数,姑且叫做bi,这就变成了b数组的递增子序列问题,dp[i]表示以bi结尾的子序列的个数,从样例数据可以知道每一个数本身就是一个子序列,dp[i]要初始化为1。对每一个bi,寻找前面比它小的递增子序列个数与自己 再构成递增子序列。时间复杂度O(n2)。

    #include<stdio.h>
    #include<iostream>
    #include<algorithm>
    #include<cstring>
    #include<math.h>
    #include<string>
    #include<map>
    #include<queue>
    #include<stack>
    #include<set>
    #define ll long long
    #define inf 0x3f3f3f3f
    using namespace std;
    
    const ll p=1e9+7;
    int n;
    double b[105];
    double c[105];///树状数组
    ll dp[105];///以i结尾的符合要求的子序列有多少个
    
    int main()///NC17065子序列 数论+dp
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        {
            double x;
            scanf("%lf",&x);
            b[i]=log(x)/(double)i;
            dp[i]=1;
        }
        ll ans=0;
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<i;j++)
            {
                if(b[j]<b[i])
                    dp[i]=(dp[i]+dp[j])%p;
            }
            ans=(ans+dp[i])%p;
        }
        printf("%lld
    ",ans);
        return 0;
    }
  • 相关阅读:
    CF899A Splitting in Teams
    CF898A Rounding
    CF914A Perfect Squares
    CF864A Fair Game
    CF909A Generate Login
    关于C++的一些函数的使用方法
    又是一个二模02,不过day2
    2模02day1题解
    二模Day2题解
    KMP算法心得
  • 原文地址:https://www.cnblogs.com/shoulinniao/p/12837072.html
Copyright © 2011-2022 走看看