zoukankan      html  css  js  c++  java
  • Luogu P3794 签到题IV

    题目大意

      给定一个长度为(n)的序列(a_1, a_2, dots , a_n)(1 leq n, a_i leq 5 imes 10^5))求有多少对$(i, j) $满足(1 leq i leq j leq n)(gcd (a_i, a_{i + 1}, dots , a_j) oplus (a_i lor a_{i + 1} lor dots lor a_j) = k)

    题解

      容易想到,当(i)不变时,随着(j)从小变大,区间(gcd)的值只会变小,且因为每次都要除以一个质因子,所以最多变小(log)次就到(1),同时区间或的值只会变大,且因为每次都会有一个二进制位变化,所以最多变大(log)次就到最大值。
      如果我们当前知道对于每个(i),所有可能出现的区间(gcd)和区间或的值,就能求出((i,j))的对数。
      同时,我们也可以由(i + 1)得到(i)可能出现的区间(gcd)和区间或的值,所以我们可以从(n)开始枚举到(1),直接求解即可。

    #include <iostream>
    #include <cstdio>
    #include <cctype>
    #include <algorithm>
    
    #define MAX_N (500000 + 5)
    #define SIZE (1 << 21)
    
    #define Getchar() (p1 == p2 && (p2 = (p1 = fr) + fread(fr, 1, SIZE, stdin), p1 == p2) ? EOF : *p1++)
    
    using namespace std;
    
    char fr[SIZE], * p1 = fr, * p2 = fr;
    
    void Read(int & res)
    {
    	res = 0;
    	char ch = Getchar();
    	while(!isdigit(ch)) ch = Getchar();
    	while(isdigit(ch)) res = res * 10 + ch - '0', ch = Getchar();
    	return; 
    }
    
    struct Interval
    {
    	int val;
    	int r;
    };
    
    int n, k;
    int a[MAX_N];
    Interval g1[25], g2[25];
    int tot1, tot2;
    long long ans;
    
    int gcd(int a, int b)
    {
    	int c;
    	while(b)
    	{
    		c = a % b;
    		a = b;
    		b = c;
    	}
    	return a;
    }
    
    void Update(int x, Interval g[], int & tot)
    {
    	g[tot + 1].val = 0x7f7f7f7f;
    	int d = 0;
    	for(int i = 1; i + d <= tot; ++i)
    	{
    		g[i] = g[i + d];
    		while(g[i + d].val == g[i + d + 1].val)
    		{
    			g[i] = g[i + d + 1];
    			++d;
    		}
    	}
    	tot -= d;
    	return;
    }
    
    int main() 
    {
    	Read(n); Read(k);
    	for(int i = 1; i <= n; ++i)
     	{
    		Read(a[i]);
    	}
    	int t1, t2;
    	g1[0].r = g2[0].r = n + 1;
    	for(int i = n; i; --i)
    	{
    		for(int j = 1; j <= tot1; ++j)
    		{
    			g1[j].val = gcd(g1[j].val, a[i]);
    		}
    		for(int j = 1; j <= tot2; ++j)
    		{
    			g2[j].val |= a[i];
    		}
    		g1[++tot1] = g2[++tot2] = (Interval){a[i], i};
    		Update(i, g1, tot1);
    		Update(i, g2, tot2);
    		t1 = tot1;
    		t2 = tot2;
    		while(t1 && t2)
    		{
    			if((g1[t1].val ^ g2[t2].val) == k) 
    			{
    				ans += min(g1[t1 - 1].r, g2[t2 - 1].r) - max(g1[t1].r, g2[t2].r);
    			}
    			if(g1[t1 - 1].r <= g2[t2 - 1].r) --t1;
    			else --t2;
    		}
    	}
    	printf("%lld", ans);
    	return 0;
    }
    
  • 相关阅读:
    How to create jar for Android Library Project
    Very large tabs in eclipse panes on Ubuntu
    64bit Ubuntu, Android AAPT, R.java
    Linux(Ubuntu)下如何安装JDK
    Configure xterm Fonts and Colors for Your Eyeball
    建立、配置和使用Activity——启动其他Activity并返回结果
    建立、配置和使用Activity——使用Bundle在Activity之间交换数据
    建立、配置和使用Activity——启动、关闭Activity
    建立、配置和使用Activity——Activity
    异步任务(AsyncTask)
  • 原文地址:https://www.cnblogs.com/kcn999/p/11355193.html
Copyright © 2011-2022 走看看