zoukankan      html  css  js  c++  java
  • Codeforces Round #523 (Div. 2) Cdp

    题:https://codeforces.com/contest/1061/problem/C

    题意:给你一个序列,我们求他们子序列的个数,这个子序列有个限制就是每一个子序列上的值都必须是能整除他的下标,问有多少个

    分析:考虑dp,我们先考虑二维的dp,定义dp[i][j]表示前i个数中,能从中提取出j个”好“序列,所以dp[i][j]就可以从dp[i-1][j-1]+dp[i-1][j]得来(前提是a[i]%j==0).显然a[i]%j!=0时dp[i][j]=dp[i-1][j]

       但这样写会MLE,所以我们将这个二维数组压缩。我们发现,我们只是在a[i]%j==0的条件下才有更新值,也就相当于前缀和,所以我们只对因子进行更新,dp[j]=dp[j]+dp[j-1]

    #include<bits/stdc++.h>
    using namespace std;
    #define pb push_back
    typedef long long ll;
    const int M=1e5+5;
    const int mod=1e9+7;
    vector<int>a[M];
    ll b[M],dp[M];
    stack<int>sta;
    void solve(int x){
        int temp=b[x];
        for(int i=1;i*i<=temp;i++){
            if(temp%i!=0)
                continue;
            if(i*i==temp)
                a[x].pb(i);
            else
                a[x].pb(i),sta.push(temp/i);
        }
        while(!sta.empty()){
            a[x].pb(sta.top());
            sta.pop();
        }
    }
    int main(){
        int n;
        cin>>n;
        for(int i=0;i<n;i++){
            scanf("%lld",&b[i]);
            solve(i);
        }
        dp[0]=1;
        for(int i=0;i<n;i++){
            for(int j=a[i].size()-1;j>=0;j--){
                int temp=a[i][j];
                if(temp<=n&&dp[temp-1]){
                    dp[temp]=(dp[temp]+dp[temp-1])%mod;
                }
            }
        }
        ll ans=0;
        for(int i=1;i<=n;i++)
            ans+=dp[i],ans%=mod;
        cout<<ans<<endl;
    }
    View Code
  • 相关阅读:
    自制flash3D变换类
    Alchemy的使用和多项式批量计算的优化
    Bresenham直线扫描算法
    模拟流体粒子运动
    任意多边形的碰撞检测——向量积判断方法
    漂亮的雪花飘落和堆积效果
    发个简单怡情的粒子随机运动
    三次贝塞尔曲线绘制算法(优化过)
    失败是成功之母
    typeid操作符
  • 原文地址:https://www.cnblogs.com/starve/p/11982915.html
Copyright © 2011-2022 走看看