模拟+Trie+桶排(归并?)+容斥
A
模(shou)拟(su)题= =感觉好像见过?
计算得分什么的……
1 //BestCoder #44 A 2 #include<vector> 3 #include<cstdio> 4 #include<cstring> 5 #include<cstdlib> 6 #include<iostream> 7 #include<algorithm> 8 #define rep(i,n) for(int i=0;i<n;++i) 9 #define F(i,j,n) for(int i=j;i<=n;++i) 10 #define D(i,j,n) for(int i=j;i>=n;--i) 11 #define pb push_back 12 using namespace std; 13 inline int getint(){ 14 int v=0,sign=1; char ch=getchar(); 15 while(ch<'0'||ch>'9'){ if (ch=='-') sign=-1; ch=getchar();} 16 while(ch>='0'&&ch<='9'){ v=v*10+ch-'0'; ch=getchar();} 17 return v*sign; 18 } 19 const int N=1e5+10,INF=~0u>>2; 20 typedef long long LL; 21 /******************tamplate*********************/ 22 const int b[]={0,1000,1500,2000,2500}; 23 24 int main(){ 25 int T=getint(); 26 F(CS,1,T){ 27 int ans=0; 28 F(i,1,4){ 29 int x=getint(),y=getint(); 30 ans+=max(b[i]*0.4,(b[i]*(250.0-x)/250.0)-y*50); 31 } 32 printf("Case #%d: %d ",CS,ans); 33 } 34 return 0; 35 }
B
给一个数组$A_i$,问$sum_{i,j} lowbit(A_i otimes A_j)$等于?
Trie树随便搞搞= =,因为从Trie上从上往下走到节点x,这个节点代表的子树中的所有数,它们的前缀是相同的(从二进制角度来看,后面xxx位都是相同的),所以前缀的异或为0,左子树中的数与右子树中的数的异或值的lowbit即为(1<<dep),dep即为当前点的深度。。。
所以遍历一遍整个Trie就可以算出来答案了= =
就是要注意一下,如果后缀都是0(从二进制角度来看是靠前的位),也要在Trie中补齐
1 //BestCoder #44 B 2 #include<vector> 3 #include<cstdio> 4 #include<cstring> 5 #include<cstdlib> 6 #include<iostream> 7 #include<algorithm> 8 #define rep(i,n) for(int i=0;i<n;++i) 9 #define F(i,j,n) for(int i=j;i<=n;++i) 10 #define D(i,j,n) for(int i=j;i>=n;--i) 11 #define pb push_back 12 using namespace std; 13 inline int getint(){ 14 int v=0,sign=1; char ch=getchar(); 15 while(ch<'0'||ch>'9'){ if (ch=='-') sign=-1; ch=getchar();} 16 while(ch>='0'&&ch<='9'){ v=v*10+ch-'0'; ch=getchar();} 17 return v*sign; 18 } 19 const int N=5e6+10,INF=~0u>>2,P=998244353; 20 typedef long long LL; 21 /******************tamplate*********************/ 22 23 int c[N][2],size[N],tot; 24 int n,m,a[N],ans; 25 26 void Insert(int v){ 27 int x=1; 28 F(i,0,30){ 29 int j=v&1; 30 if (!c[x][j]) c[x][j]=++tot; 31 size[x]++; 32 x=c[x][j]; v>>=1; 33 } 34 size[x]++; 35 } 36 void dp(int x,int len){ 37 if (!x||size[x]==1) return; 38 // printf("dp %d %d ",x,len); 39 // printf("size[L]=%d size[R]=%d ",size[c[x][0]],size[c[x][1]]); 40 ans=((LL)ans+(LL)size[c[x][0]]*size[c[x][1]]%P*(1<<len)%P)%P; 41 dp(c[x][0],len+1); dp(c[x][1],len+1); 42 } 43 int main(){ 44 #ifndef ONLINE_JUDGE 45 freopen("B.in","r",stdin); 46 freopen("B.out","w",stdout); 47 #endif 48 int T=getint(); 49 F(cs,1,T){ 50 printf("Case #%d: ",cs); 51 n=getint(); 52 memset(c,0,sizeof c); tot=1; 53 memset(size,0,sizeof size); 54 F(i,1,n){ 55 a[i]=getint(); 56 Insert(a[i]); 57 } 58 ans=0; 59 dp(1,0); 60 printf("%d ",(ans*2)%P); 61 /* ans=0; 62 F(i,1,n) F(j,1,n){ 63 int tmp=a[i]^a[j]; 64 ans+=tmp&(-tmp); 65 } 66 printf("%d ",ans); 67 */ } 68 return 0; 69 }
C
这个题其实我不会做= =
我yy的方法是:对A数组建出一棵Trie,然后对于每一个在B中的数,从Trie上往下走,向0走的时候b[i]>>=1,向1走的时候b[i]=(b[i]+1>>1)(执行加法)
然而这样是$O(n^2*log^2n)$的……这样做还不如暴力2333
膜了jiry_2老司机的代码,原来是从高位到低位依次计算,桶排一下,将这一位是0的放到一起,是1的放到一起……然后利用一下容斥原理&单调性,搞出和中这一位是1的数量,异或一下。。。
1 //BestCoder #44 C 2 #include<vector> 3 #include<cstdio> 4 #include<cstring> 5 #include<cstdlib> 6 #include<iostream> 7 #include<algorithm> 8 #define rep(i,n) for(int i=0;i<n;++i) 9 #define F(i,j,n) for(int i=j;i<=n;++i) 10 #define D(i,j,n) for(int i=j;i>=n;--i) 11 #define pb push_back 12 using namespace std; 13 typedef long long LL; 14 inline LL getint(){ 15 LL v=0,sign=1; char ch=getchar(); 16 while(ch<'0'||ch>'9'){ if (ch=='-') sign=-1; ch=getchar();} 17 while(ch>='0'&&ch<='9'){ v=v*10+ch-'0'; ch=getchar();} 18 return v*sign; 19 } 20 const int N=1e5+10,INF=~0u>>2; 21 /******************tamplate*********************/ 22 23 int n,tot; 24 vector<LL>A[2]; 25 LL x[N],y[N]; 26 int main(){ 27 #ifndef ONLINE_JUDGE 28 freopen("C.in","r",stdin); 29 freopen("C.out","w",stdout); 30 #endif 31 int T=getint(); 32 F(cs,1,T){ 33 printf("Case #%d: ",cs); 34 n=getint(); 35 F(i,1,n) x[i]=getint(); 36 F(i,1,n) y[i]=getint(); 37 LL num=0; 38 F(now,0,61){ 39 A[0].clear(); A[1].clear(); 40 F(i,1,n) A[x[i]>>now&1].pb(x[i]); 41 int head=0; 42 rep(i,A[0].size()) x[++head]=A[0][i]; 43 rep(i,A[1].size()) x[++head]=A[1][i]; 44 A[0].clear(); A[1].clear(); 45 F(i,1,n) A[y[i]>>now&1].pb(y[i]); 46 head=0; 47 rep(i,A[0].size()) y[++head]=A[0][i]; 48 rep(i,A[1].size()) y[++head]=A[1][i]; 49 LL tot=(1LL<<(now+1))-1,lim=1LL<<now,lim2=(1LL<<now+1),ans=0; 50 int a=0,b=0,c=0; 51 D(i,n,1){ 52 while(a<n && (x[i]&tot)+(y[a+1]&tot)<lim)a++; 53 while(b<n && (x[i]&tot)+(y[b+1]&tot)<lim2)b++; 54 while(c<n && (x[i]&tot)+(y[c+1]&tot)<lim+lim2)c++; 55 ans+=n-c+b-a; 56 } 57 if (ans&1) num|=(1LL<<now); 58 } 59 printf("%lld ",num); 60 } 61 return 0; 62 }