zoukankan      html  css  js  c++  java
  • Codeforces round #717 D.Cut(m询问求区间[L,R]能被至少分成多少个区间让每个小区间各数的乘积==各数的LCM)

    题:https://codeforces.com/contest/1516/problem/D

    题意:给定n(n<=1e5)个数,q(n<=1e5)个询问,[L,R],问:[L,R]能被至少分成多少个区间让每个小区间各数的乘积==各数的LCM

    分析:

    • 考虑最简单的求法,对于每个 l ,求出b[l],使得[ l, b[l] ]满足题意,然后迭代l = b[l] 直到 l 超过 r,计数结束;
    • 简化这个迭代的过程,考虑dp[ i ][ j ]表示进行了 j = b[ j ] 这个操作 2 ^ i 次到达的位置;
    • 而只要算出每个位置迭代1次(即迭代2^0次)就能递推出所有dp[ i ][ j ]( 因为可以满足dp[ i ][ j ] = dp[i - 1][ dp[i - 1][ j ] ] );
    • 对于迭代一次的可以预处理每个数的质数,然后从后往前枚举离当前位置pos最近又含与a[pos]不互质的位置 j ,这个位置 j 就是pos迭代一次要跳的位置;
    • 因为询问的[L, R]之间的距离肯定可以由一个二进制数来定,所以可以用这个方法。
    #include<bits/stdc++.h>
    using namespace std;
    #define pb push_back
    #define MP make_pair
    #define UM unordered_map
    #define pii pair<int,int>
    #define lson root<<1,l,midd
    #define rson root<<1|1,midd+1,r
    #define lc root<<1
    #define rc root<<1|1
    typedef long long ll;
    const int mod=1e9+7;
    const int inf=0x3f3f3f3f;
    const ll INF=1e18;
    #define pi 3.1415926535898
    #define DEC (pi/180)
    const int M=1e5+5;
    vector<int>vec[M];
    int dp[20][M*10],nextt[M],a[M];
    int n,q;
    void init(){
        for(int i=2;i<M;i++){
            if(vec[i].size()==0){
                nextt[i]=n+1;
                for(int j=i;j<M;j+=i){
                    vec[j].pb(i);
                }
            }
        }
    }
    int main(){
    
        int T;
        ///scanf("%d",&T);
        T=1;
        while(T--){
            scanf("%d%d",&n,&q);
            for(int i=1;i<=n;i++){
                nextt[i]=n+1;
                scanf("%d",&a[i]);
            }
            init();
            dp[0][n+1]=n+1;
            for(int j=n;j>=1;j--){
                dp[0][j]=dp[0][j+1];
                for(auto v:vec[a[j]]){
                    dp[0][j]=min(dp[0][j],nextt[v]);
                    nextt[v]=j;
                }
            }
            for(int i=1;i<20;i++)
                for(int j=1;j<=n+1;j++)
                    dp[i][j]=dp[i-1][dp[i-1][j]];
            while(q--){
                int L,R;
                scanf("%d%d",&L,&R);
                int ans=1;
                for(int i=19;i>=0;i--){
                    if(dp[i][L]<=R){
                        ans+=(1<<i);
                        L=dp[i][L];
                    }
                }
                printf("%d
    ",ans);
            }
        }
        return 0;
    }
    View Code
  • 相关阅读:
    自适应网页设计(Responsive Web Design)(转)
    PAT 1062 最简分数(20)(代码+思路)
    PAT 1059 C语言竞赛(20)(代码+思路)
    PAT 1058 选择题(20)(代码+思路)
    PAT 1057 数零壹 (20)(代码+思路)
    PAT 1054 求平均值 (20)(代码+思路+测试用例)
    PAT 1053 住房空置率 (20)(代码+思路)
    PAT 1052 卖个萌 (20)(代码+思路)
    PAT 1048 数字加密(20)(代码+思路)
    PAT 1047 编程团体赛(代码)
  • 原文地址:https://www.cnblogs.com/starve/p/14689402.html
Copyright © 2011-2022 走看看