1. 程式人生 > 實用技巧 >CF243A The Brand New Function

CF243A The Brand New Function

CF243A The Brand New Function

洛谷傳送門

題意翻譯

題目大意

Polycarpus有一個由n個非負整陣列成的序列

我們定義函式f(l,r)(1 \le l,r \le n)f(l,r)(1≤l,rn),表示序列的子串[l,r]各項的“或”和:f(l,r)=a_l|a_{l+1}|⋯|a_rf(l,r)=a**la**l+1∣⋯∣a**r

Polycarpus在紙上寫下了所有的f(l,r)的值,他想知道他寫下了多少個不同的值

輸入

第一行1個整數n(1 \le n \le 10^5)n(1≤n≤105),表示序列a的元素個數。

第二行nn個整數,表示序列各項元素a_i(0 \le a_i \le 10^6)a**i

(0≤a**i≤106)。

輸出

輸出f(l,r)f(l,r)有多少個不同的值。

樣例解釋

第一個樣例中:66個f(l,r)f(l,r)分別為:f(1,1)=1,f(1,2)=3,f(1,3)=3,f(2,2)=2,f(2,3)=2,f(3,3)=0f(1,1)=1,f(1,2)=3,f(1,3)=3,f(2,2)=2,f(2,3)=2,f(3,3)=0。有4種不同的值:00, 11, 22, 33.


題解:

一開始想維護一棵線段樹+遍歷線段樹。

過了所有樣例,但是假了,因為線段樹維護的區間並不是全部區間,所以不能直接這麼維護。

於是開始想推性質。思考每次轉移會對答案造成何種影響。失敗。

最後看題解之後發現可以直接暴力列舉+剪枝。

很容易發現,暴力是\(n^2\)的。但是可以剪枝。當一個數各位都是1的話,怎麼或都沒有用了,直接剪枝。

程式碼:

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e6+6;
int a[maxn],n;
set<int>s;
int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
		scanf("%d",&a[i]);
	for(int i=1;i<=n;i++)
	{
		int x=a[i],y=0;
		s.insert(x);
		for(int j=i+1;j<=n;j++)
		{
			x|=a[j];
			y|=a[j];
			s.insert(x);
			if(x==y)
				break;
		}
	}
	printf("%d\n",s.size());
	return 0;
}