zoukankan      html  css  js  c++  java
  • [自测]LCM

    题目

    多次询问区间([l,r]),求区间所有数的(lcm),答案对(10^9+7)取模,强制在线,(l,rleq 10^5)

    解法1

    构造一个数组(d_i),对每个质数的开一个栈,记录它出现的位置

    对于位置(i)构造一个(d_i),如果(i)有一个质因子(p^k),将栈中的前(k)个元素弹出,加入这个质因子,并令(d_i=i)
    对于被弹出的元素,假设它的位置是(l),那么(d_l/=p)

    对于询问([l,r]),只构造到(d_r),那么(prod_{i=l}^r d_i)即为答案,用线段树维护区间乘法

    可以发现([1,r])状态由([1,r-1])继承,所以用可持久化线段树即可

    时间复杂度(O(qlog^2n)),空间复杂度(O(nlogn))

    解法2

    定义数组(w_i),如果(i=p^k),那么(w_i=p),否则(w_i=1)

    对于询问([l,r])(w_{p^k})有贡献当且仅当(p^k)的倍数落在([l,r])里面,即(lfloor frac{l-1}{p^k} floor eq lfloor frac{r}{p^K} floor)

    那么(ans_{[l,r]}=prod_{i=1}^r imes [lfloor frac{l-1}{p^k} floor eq lfloor frac{r}{p^K} floor])

    时间复杂度(O(qsqrt{n})),空间复杂度(O(n))

    #include<bits/stdc++.h>
    #define N 100005
    using namespace std;
    typedef long long ll;
    const ll mod = 1000000007;
    int T,n,k,A,B,mo,c[200005],d[200005];
    int w[N],p[N],cnt;
    ll pre[N],inv[N],las;
    bool isnotp[N];
    
    template <class T> inline T Max(T a,T b) { return a > b ? a : b; }
    template <class T> inline T Min(T a,T b) { return a < b ? a : b; }
    template <class T> void read(T &x)
    {
    	char c;int sign=1;
    	while((c=getchar())>'9'||c<'0') if(c=='-') sign=-1; x=c-48;
    	while((c=getchar())>='0'&&c<='9') x=(x<<1)+(x<<3)+c-48; x*=sign;
    }
    ll qp(ll a,ll b) { ll ret=1; for(;b;b>>=1,a=a*a%mod) if(b&1) ret=ret*a%mod; return ret; }
    void init(int maxn)
    {
    	w[1]=1;
    	for(int i=2;i<=maxn;++i)
    	{
    		if(!isnotp[i]) p[++cnt]=i;
    		for(int j=1;j<=cnt&&(ll)p[j]*i<=maxn;++j)
    		{
    			w[p[j]*i]=1;
    			isnotp[p[j]*i]=1;
    			if(i%p[j]==0) break;
    		}
    	}
    	for(int i=1;i<=cnt;++i)
    	  for(ll x=p[i];x<=maxn;x*=p[i]) w[x]=p[i];
    	pre[0]=1;inv[0]=1;
    	for(int i=1;i<=maxn;++i) pre[i]=pre[i-1]*w[i]%mod;
    	for(int i=1;i<=maxn;++i) inv[i]=qp(pre[i],mod-2);
    	
    //	for(int i=1;i<=100;++i) cout<<i<<' '<<w[i]<<endl;
    }
    void solve(int n,int k)
    {
    	int L=n-k,R=n;
    	ll ans=1;
    	for(int l=1,r;l<=R;l=r+1)
    	{
    		if(L/l) r=Min(R/(R/l) , L/(L/l));
    		else r=R/(R/l);
    		if(L/l != R/l) ans=ans * pre[r]%mod * inv[l-1]%mod;
    	}
    	las=ans;
    	printf("%lld
    ",ans);
    }
    int main()
    {
    	freopen("num.in","r",stdin);
    	freopen("num.out","w",stdout);
    	init(N-5);
    	read(T); --T;
    	read(n);read(k);
    	solve(n,k);
    	read(A);read(B);read(mo);
    	for(int i=1;i<=T;++i) read(c[i]);
    	for(int i=1;i<=T;++i) read(d[i]);
    	for(int i=1;i<=T;++i)
    	{
    		n=(A*las+c[i])%mo+1;
    		k=(B*las+d[i])%n+1;
    		solve(n,k);
    	}
    	return 0;
    }
    
  • 相关阅读:
    c++ socket发送数据时,sendData = char * string 导致的乱码问题
    c++ sprintf() 用法
    c++ 将float 类型转换成string 类型
    c++中 string类型 转为 char []类型
    c++ 去掉所有空格及换行符
    c++处理字符串string.find()与string::npos
    C1010 unexpected end of file while looking for precompiled header. Did you forget to add '#include "stdafx.h"' to your source
    C++ socket bind() 函数绑定错误
    windows 全局安装 composer
    VMware Tools (ubuntu系统)安装详细过程与使用
  • 原文地址:https://www.cnblogs.com/Chtholly/p/11988482.html
Copyright © 2011-2022 走看看