• [JZOJ4307]喝喝喝--枚举


    [JZOJ4307]喝喝喝--枚举

    题目链接

    自行搜索

    分析

    我们需要找到所有不包含((a_x,a_y),a_x equiv k mod a_y (x<y))这样的连续数对,转化一下变成(a_x-k equiv 0 mod a_y).

    考虑从左到右加数,可以发现如果(a_i - k equiv 0 mod a_j),那么起点为(i),终点大于等于(j)的连续序列都是不合法的,于是维护一个左指针(lst),表示当前距离最近的不合法起点,换句话说,(lst+1)到当前遍历的数这一段都是合法的

    怎么更新(f[x])?由于值域范围很小((1e5)),我们设若当前加的第(i)个数为(x),设(f[x])为当前距(i)最近的(y)使得(x - k equiv 0 mod a_y),每次新加入一个数就比较(f[x])(lst)哪个更大,这样就能更新(lst),同时加完(x)这个数后,我们可以在(O( sqrt{x} ))的时间内将所有满足(x -k equiv 0 mod p)(p)找出来更新它们的(f)

    当时要注意我们这种方法会漏掉前面有数为(k)的情况,要特判

    代码

    /*
      code by RyeCatcher
    */
    inline char gc(){
        static char buf[SIZE],*p1=buf,*p2=buf;
        return p1==p2&&(p2=(p1=buf)+fread(buf,1,SIZE,stdin),p1==p2)?EOF:*p1++;
    }
    #define gc getchar
    template <class T>inline void read(T &x){
        x=0;int ne=0;char c;
        while((c=gc())>'9'||c<'0')ne=c=='-';x=c-48;
        while((c=gc())>='0'&&c<='9')x=(x<<3)+(x<<1)+c-48;x=ne?-x:x;return ;
    }
    const int maxn=1000005;
    const int inf=0x7fffffff;
    int f[maxn],kk=0,lst=0;
    int n,k;
    ll ans=0;
    int main(){
    	int x;
    	FO(drink);
    	//freopen("drink6.in","r",stdin);
    	read(n),read(k);
    	for(ri i=1;i<=n;i++){
    		read(x);
    		if(x>k){
    			if(f[x]>lst)lst=f[x];
    			if(kk>lst)lst=kk;
    		}
    		ans+=i-lst;
    		if(x==k)kk=i;
    		else if(x<k)continue;
    		x-=k;
    		for(ri j=1;j<sqrt(x+0.5);j++){
    			if(x%j==0)f[j]=f[x/j]=i;
    		}
    	}
    	printf("%lld
    ",ans);
    	return 0;
    }
    
    
  • 相关阅读:
    C语言 数组排序 – 冒泡法排序
    类加载过程
    布隆过滤器的原理及应用
    回答两个被频繁问到的代码写法问题
    关于分布式事务的理解
    根据使用者反馈,对开源项目 go-gin-api 新增两个功能
    图书速度 | 《如何高效学习》
    报错kernel:NMI watchdog: BUG: soft lockup
    容器Jenkins中运行docker
    容器Jenkins中运行docker
  • 原文地址:https://www.cnblogs.com/Rye-Catcher/p/9807682.html
Copyright © 2020-2023  润新知