把博客园图标替换成自己的图标
把博客园图标替换成自己的图标end

CF243A The Brand New Function

题面传送门
题解里居然没有对这个东西复杂度严格证明的,我来补一发。
首先暴力\(O(n^2)\)不再赘述。
可以加上一些剪枝,如果我们对于每个\(i\)倒序枚举每个\(j\),那么如果\(a_j|a_{j+1}|⋯|a_i=a_j|a_{j+1}|⋯|a_{i-1}\),那么就不用往下枚举,因为接下来的一定与前一个所枚举的相同。
然后,就过了。
代码实现:

#include<cstdio>
using namespace std;
int n,m,k,x,y,z,a[100039],f[2000039],ans;
int main(){
	//freopen("1.in","r",stdin);
	register int i,j;
	scanf("%d",&n);
	for(i=1;i<=n;i++) scanf("%d",&a[i]);
	for(i=1;i<=n;i++){
		if(!f[a[i]]) ans++,f[a[i]]=1;
		for(j=i-1;j;j--){
			if(a[j]==(a[i]|a[j])) break;
			a[j]|=a[i];
			if(!f[a[j]]) ans++,f[a[j]]=1;
		}
	}
	printf("%d\n",ans);
}

那么为什么这样子复杂度是对的呢?这样子看上去就是\(O(n^2)\)的。
观察a[j]|=a[i];这条语句,即如果进入这条语句,\(a_j\)至少有一个二进制位由\(0\)变成\(1\),则对于每个\(a_j\),最多只会被操作\(loga_j\)次,则总复杂度为\(O(nloga_i)\),可以通过本题。

posted @ 2021-01-02 20:19  275307894a  阅读(88)  评论(0编辑  收藏  举报
浏览器标题切换
浏览器标题切换end