zoukankan      html  css  js  c++  java
  • [bzoj5472] 数列

    Description

    输入一个长度为n的数组{ai}(1 <= i <= n)

    问有多少个长度为n的数组{xi}(1 <= i <= n),满足1 <= xi <= ai。

    并且相邻两项的最大公约数小于等于k。

    换句话说,对于1<i <= n,满足gcd(xi−1,xi) <= k。

    问这样的数组{xi}有多少个,答案对1000000007取模。

    Input

    第一行两个整数n,k。接下来一行n个整数,表示数组{ai}。

    1 <= ai,k <= 1000000。Sigma(ai) <= 1000000。

    Output

    一行一个整数表示这样的数组的个数,对1000000007取模。

    Sample Input

    9 2
    1 2 3 4 5 6 7 8 9
    

    Sample Output

    168852
    

    Solution

    考虑(dp)

    (f_{i,j})表示当前选到第(i)个数了,这个数选的是(j)

    显然可以得到转移:

    [f_{i,j}=sum_{x=1}^{lim_{i-1}}f_{i-1,x}[gcd(j,x)leqslant k] ]

    这个是(O(n^2))的,不能接受,考虑针对后面的(gcd)化简式子,莫比乌斯反演一波可以得到:

    [f_{i,j}=sum_{T|j}sum_{t|T}mu(t)[frac{T}{t}leqslant k]sum_{x=1}^{frac{lim_{i-1}}{T}}f_{i-1,xT} ]

    中间都是一些套路的化简,这里不赘述了。

    然后设:

    [g(n)=sum_{t|n}mu(t)[frac{n}{t}leqslant k] ]

    这个可以(O(nlog n))预处理出来。

    设:

    [h(x)=sum_{i=1}^{frac{lim_{i-1}}{x}}f_{i-1,ix} ]

    这个每次转移都是(O(limcdot log lim)),总复杂度(O(nlog n))

    所以转移可以写成这样:

    [f_{i,j}=sum_{t|j}g(t)h(t) ]

    这个可以枚举约数(O(nlog n))

    所以,总复杂度为(O(nlog n))

    #pragma GCC optimize(3)
    #include<bits/stdc++.h>
    using namespace std;
    
    const int mod = 1000000007;
    
    void read(int &x) {
        x=0;int f=1;char ch=getchar();
        for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-f;
        for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';x*=f;
    }
     
    void print(int x) {
        if(x<0) putchar('-'),x=-x;
        if(!x) return ;print(x/10),putchar(x%10+48);
    }
    void write(int x) {if(!x) putchar('0');else print(x);putchar('
    ');}
    
    const int maxn = 2e6+10;
    
    vector <int > f[maxn];
    
    int g[maxn],mu[maxn],pri[maxn],tot,vis[maxn],k,n,lim[maxn],h[maxn],G[maxn];
    
    void sieve() {
    	mu[1]=1;
    	for(int i=2;i<maxn;i++) {
    		if(!vis[i]) pri[++tot]=i,mu[i]=-1;
    		for(int j=1;j<=tot&&i*pri[j]<maxn;j++) {
    			vis[i*pri[j]]=1;
    			if(i%pri[j]==0) break;
    			mu[i*pri[j]]=-mu[i];
    		}
    	}
    	for(int t=1;t<maxn;t++)
    		for(int d=t;d<maxn&&d<=k*t;d+=t) g[d]+=mu[t];
    }
    
    int main() {
    	read(n),read(k);
    	sieve();
    	for(int i=1;i<=n;i++) {
    		read(lim[i]);
    		for(int j=0;j<=lim[i]+1;j++) f[i].push_back(0);
    	}
    	for(int i=1;i<=lim[1];i++) f[1][i]=1;
    	for(int i=2;i<=n;i++) {
    		for(int j=1;j<=lim[i];j++) h[j]=0;   // ATTENTION lim[i] !
    		for(int j=1;j<=lim[i-1];j++)
    			for(int u=j;u<=lim[i-1];u+=j) h[j]=(h[j]+f[i-1][u])%mod;
    		for(int t=1;t<=lim[i];t++)
    			for(int d=t;d<=lim[i];d+=t) 
    				f[i][d]=(1ll*f[i][d]+1ll*h[t]*g[t]%mod)%mod;
    	}
    	int ans=0;
    	for(int i=1;i<=lim[n];i++) ans=(ans+f[n][i])%mod;
    	write((ans%mod+mod)%mod);
    	return 0;
    }
    
  • 相关阅读:
    模板汇总——Tarjian
    CountHunter 6101 最优贸易 强联通缩点
    POJ-3662 Telephone Lines 二分+双端队列
    EF-获取自增ID值
    EF-记录程序自动生成并执行的sql语句日志
    EF-使用迁移技术让程序自动更新数据库表结构
    EF-关于类库中EntityFramework之CodeFirst(代码优先)的操作浅析
    javascript进阶笔记(3)
    javascript进阶笔记(2)
    javascript进阶笔记(1)
  • 原文地址:https://www.cnblogs.com/hbyer/p/10283015.html
Copyright © 2011-2022 走看看