CF243A The Brand New Function
阿新 • • 發佈:2020-11-27
CF243A The Brand New Function
題意翻譯
題目大意
Polycarpus有一個由n個非負整陣列成的序列
我們定義函式f(l,r)(1 \le l,r \le n)f(l,r)(1≤l,r≤n),表示序列的子串[l,r]各項的“或”和:f(l,r)=a_l|a_{l+1}|⋯|a_rf(l,r)=a**l∣a**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
輸出
輸出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; }