这个比赛跟前两场区别度还是挺大的,水题和简单题少了,而且昨天中午也有事,让队友先打了,回来发现只有3题有人ac,于是看了看题
先看了B,大意就是给一个序列,满足For every <var>i</var> in [1,<var>n</var>-1] , (<var>a</var>[<var>i</var>] xor <var>S</var>) ≤ (<var>a</var>[<var>i</var>+1] xor <var>S</var>),然后问s最多有多少种情况。
二进制异或的话,其实就是暴力吧,每两个两个进行判断,看能否确定s的某些特性,最后发现其实要满足这个式子只需要让两个数的二进制从后向前进行判断,如果相同就不变,如果不同的话,再分如果a【n+1】的这个位置为1的话,s的这个位置就为0,这时就满足了上式,也就确定了,s的一个位置,然后同理,每次比较两个数都能确定一个位置,(但是可能确定的同一个位置),就可以用60减去确定的位置就可以确定有多少没有确定的位置,然后每个不确定位置都存在两种情况,答案就可以确定了。(附:有一种情况还是需要考虑的就是存在一种情况,使得s的某一个位置产生矛盾,但是其实可以排除的,因为只要第二次要更改s的这个位置时更改这个位置的前一个位置或后一个位置就行了)还有就是数据是2^60,要爆int的,用long long。
然后,附上代码
#include <cstdio> #include <iostream> #include <algorithm> #include <cmath> #include <set> #include <map> #include <queue> #include <cstring> using namespace std; int s[65]; void cmp(long long x,long long y){ int a[65]={0},b[65]={0}; int n=0,m=0; while(x>0){ a[n++]=x%2; x/=2; } while(y>0){ b[m++]=y%2; y/=2; } for(int i=59;i>=0;i--){ if(a[i]!=b[i]){ s[i]=1; break; } } return ; } int main() { unsigned long long num[55]; int n; int m=0; cin>>n; memset(s,0,sizeof(s)); for(int i=0;i<n;i++) cin>>num[i]; for(int i=0;i<n-1;i++) cmp(num[i],num[i+1]); for(int i=0;i<60;i++) if(s[i]==0) m++; long long sum=(long long)1<<m; cout<<sum<<endl; return 0; }
然后看了H题过的人挺多的,就先去看了H题,其实就是一个模拟,模拟操作,然后就是在输入的时候除了def以为其他都是输入三个字符串,所以在输入的时候加个if,然后就是模拟这些操作吧,也没有什么坑,就按他上面说的进行操作输出就行了。
#include <iostream> #include <algorithm> #include <cmath> #include <set> #include <map> #include <queue> #include <cstring> using namespace std; unsigned long long mod=1; int main() { int n=0,m=0; unsigned long long d; string s,a,b,c; map<string,unsigned long long>t; for(int i=0;i<47;i++) mod*=2; while(cin>>a>>b){ if(a=="def") cin>>d; else cin>>c; if(a=="def"){ t[b]=d; cout<<b<<" = "<<d<<endl; } if(a=="add"){ cout<<b<<" = "<<(t[b]+t[c])%mod<<endl; t[b]=(t[b]+t[c])%mod; } if(a=="sub"){ cout<<b<<" = "; long long ss=t[b]-t[c]; if(ss<0) ss+=mod; cout<<ss<<endl; t[b]=ss; } if(a=="mul"){ cout<<b<<" = "<<(t[b]*t[c])%mod<<endl; t[b]=(t[b]*t[c])%mod; } if(a=="div"){ cout<<b<<" = "<<(t[b]/t[c])%mod<<endl; t[b]=(t[b]/t[c])%mod; } if(a=="mod"){ cout<<b<<" = "<<(t[b]%t[c])%mod<<endl; t[b]=(t[b]%t[c])%mod; } } return 0; }
队友把C题和G题给过了,G题应该是签到题,没看,C题看了看题目,感觉也是模拟,每次改下自己名次前的人数,好像队友是用队列进行维护的,感觉用数组也行,就是每次有人过题时候,跟自己判断一下,如果超过了,就加进去,然后自己过题的时候,把数组里的元素每个都判断一下,被超过就踢出。
因为不是自己写的就不贴代码了
最后把I题看了看,队友写了一个O(N^3)的写法,我帮忙写了个费马小定理求逆元的除法取模,但是发现TLE,优化不了,就放弃了。。。