二进制专场,还被FST一题。
A、签到,题意是,给定a,b,c
f(0)=a,f(1)=b,f(n)=f(n-1)^f(n-2)
求f(n)
稍微化简就看得出f(x)是按照a,b,a^b这样在循环出现
因为a^b^a=b,a^b^b=a
代码:
#include <bits/stdc++.h> #define int long long #define sc(a) scanf("%lld",&a) #define scc(a,b) scanf("%lld %lld",&a,&b) #define sccc(a,b,c) scanf("%lld %lld %lld",&a,&b,&c) #define schar(a) scanf("%c",&a) #define pr(a) printf("%lld",a) #define fo(i,a,b) for(int i=a;i<b;++i) #define re(i,a,b) for(int i=a;i<=b;++i) #define rfo(i,a,b) for(int i=a;i>b;--i) #define rre(i,a,b) for(int i=a;i>=b;--i) #define prn() printf("\n") #define prs() printf(" ") #define mkp make_pair #define pii pair<int,int> #define pub(a) push_back(a) #define pob() pop_back() #define puf(a) push_front(a) #define pof() pop_front() #define fst first #define snd second #define frt front() #define bak back() #define mem0(a) memset(a,0,sizeof(a)) #define memmx(a) memset(a,0x3f3f,sizeof(a)) #define memmn(a) memset(a,-0x3f3f,sizeof(a)) #define debug #define db double #define yyes cout<<"YES"<<endl; #define nno cout<<"NO"<<endl; using namespace std; typedef vector<int> vei; typedef vector<pii> vep; typedef map<int,int> mpii; typedef map<char,int> mpci; typedef map<string,int> mpsi; typedef deque<int> deqi; typedef deque<char> deqc; typedef priority_queue<int> mxpq; typedef priority_queue<int,vector<int>,greater<int> > mnpq; typedef priority_queue<pii> mxpqii; typedef priority_queue<pii,vector<pii>,greater<pii> > mnpqii; const int maxn=500005; const int inf=0x3f3f3f3f3f3f3f3f; const int MOD=100000007; const db eps=1e-10; int qpow(int a,int b){int tmp=a%MOD,ans=1;while(b){if(b&1){ans*=tmp,ans%=MOD;}tmp*=tmp,tmp%=MOD,b>>=1;}return ans;} int lowbit(int x){return x&-x;} int max(int a,int b){return a>b?a:b;} int min(int a,int b){return a<b?a:b;} int mmax(int a,int b,int c){return max(a,max(b,c));} int mmin(int a,int b,int c){return min(a,min(b,c));} void mod(int &a){a+=MOD;a%=MOD;} bool chk(int now){} int half(int l,int r){while(l<=r){int m=(l+r)/2;if(chk(m))r=m-1;else l=m+1;}return l;} int ll(int p){return p<<1;} int rr(int p){return p<<1|1;} int mm(int l,int r){return (l+r)/2;} int lg(int x){if(x==0) return 1;return (int)log2(x)+1;} bool smleql(db a,db b){if(a<b||fabs(a-b)<=eps)return true;return false;} db len(db a,db b,db c,db d){return sqrt((a-c)*(a-c)+(b-d)*(b-d));} bool isp(int x){if(x==1)return false;if(x==2)return true;for(int i=2;i*i<=x;++i)if(x%i==0)return false;return true;} int t,a,b,n; signed main(){ ios_base::sync_with_stdio(0); cin.tie(0),cout.tie(0); cin>>t; while(t--){ cin>>a>>b>>n; if(n==0) cout<<a<<endl; else if(n==1) cout<<b<<endl; else{ int k=n%3; if(k==0) cout<<a<<endl; else if(k==1) cout<<b<<endl; else cout<<(a^b)<<endl; } } return 0; }
B、被FST的一道题,题意是选定一个[l,r]的连续区间将它删去,使得剩下的数字两两不相同,不需要删去输出0即可
连续子段的问题我上了尺取法,假设[l,r]的区间是我要删去的区间,在确定l的情况下不断把r减小,来找到最小的区间。
一开始过不了pp,想了一下发现是删除开始和结尾一段连续区间的情况没有考虑到,加了一下判断过了pp。
后来找半天小一点的hack,终于让我给翻到了:
8 1 2 3 4 2 6 5 4
显然应该删除第四位和第五位上的2,4,但是我却输出了3,debug时候发现[l,r]区间根本就没有遍历到第四位和第五位上去。
看正解发现是O(n^2logn)的,大意是删除一段子区间之后只会留下一个前缀和一个后缀,它们的长度可以为0
那么枚举没有重复长度的前缀,找到最长的没有任何重复数字的后缀,用map维护住即可,注意前后缀都为空的下标细节
代码:
#include <bits/stdc++.h> #define int long long #define sc(a) scanf("%lld",&a) #define scc(a,b) scanf("%lld %lld",&a,&b) #define sccc(a,b,c) scanf("%lld %lld %lld",&a,&b,&c) #define schar(a) scanf("%c",&a) #define pr(a) printf("%lld",a) #define fo(i,a,b) for(int i=a;i<b;++i) #define re(i,a,b) for(int i=a;i<=b;++i) #define rfo(i,a,b) for(int i=a;i>b;--i) #define rre(i,a,b) for(int i=a;i>=b;--i) #define prn() printf("\n") #define prs() printf(" ") #define mkp make_pair #define pii pair<int,int> #define pub(a) push_back(a) #define pob() pop_back() #define puf(a) push_front(a) #define pof() pop_front() #define fst first #define snd second #define frt front() #define bak back() #define mem0(a) memset(a,0,sizeof(a)) #define memmx(a) memset(a,0x3f3f,sizeof(a)) #define memmn(a) memset(a,-0x3f3f,sizeof(a)) #define debug #define db double #define yyes cout<<"YES"<<endl; #define nno cout<<"NO"<<endl; using namespace std; typedef vector<int> vei; typedef vector<pii> vep; typedef map<int,int> mpii; typedef map<char,int> mpci; typedef map<string,int> mpsi; typedef deque<int> deqi; typedef deque<char> deqc; typedef priority_queue<int> mxpq; typedef priority_queue<int,vector<int>,greater<int> > mnpq; typedef priority_queue<pii> mxpqii; typedef priority_queue<pii,vector<pii>,greater<pii> > mnpqii; const int maxn=500005; const int inf=0x3f3f3f3f3f3f3f3f; const int MOD=100000007; const db eps=1e-10; int qpow(int a,int b){int tmp=a%MOD,ans=1;while(b){if(b&1){ans*=tmp,ans%=MOD;}tmp*=tmp,tmp%=MOD,b>>=1;}return ans;} int lowbit(int x){return x&-x;} int max(int a,int b){return a>b?a:b;} int min(int a,int b){return a<b?a:b;} int mmax(int a,int b,int c){return max(a,max(b,c));} int mmin(int a,int b,int c){return min(a,min(b,c));} void mod(int &a){a+=MOD;a%=MOD;} bool chk(int now){} int half(int l,int r){while(l<=r){int m=(l+r)/2;if(chk(m))r=m-1;else l=m+1;}return l;} int ll(int p){return p<<1;} int rr(int p){return p<<1|1;} int mm(int l,int r){return (l+r)/2;} int lg(int x){if(x==0) return 1;return (int)log2(x)+1;} bool smleql(db a,db b){if(a<b||fabs(a-b)<=eps)return true;return false;} db len(db a,db b,db c,db d){return sqrt((a-c)*(a-c)+(b-d)*(b-d));} bool isp(int x){if(x==1)return false;if(x==2)return true;for(int i=2;i*i<=x;++i)if(x%i==0)return false;return true;} int n,a[maxn]; mpii mp; signed main(){ ios_base::sync_with_stdio(0); cin.tie(0),cout.tie(0); cin>>n; re(i,1,n) cin>>a[i]; int ans=n-1; re(i,1,n){ bool can=1; mp.clear(); re(j,1,i-1){ mp[a[j]]++; if(mp[a[j]]==2){ can=0; break; } } int p=n+1; rre(j,n,i){ mp[a[j]]++; if(mp[a[j]]==1) p=j; else break; } if(can) ans=min(ans,p-i); } cout<<ans; return 0; } /* 6 2 2 3 3 4 2 8 1 2 3 4 2 6 5 4 10 7 6 5 4 3 2 1 7 7 7 */
C、给定一个n,保证n是4的倍数,构造一个n*n的矩阵,使得[0,n^2-1]当中的每个数字仅出现一次,并且矩阵每一行每一列异或和为相同
先猜个结论,行列异或和都为0
比赛的时候ly给的解法是四个四个分组,我没太看懂,比赛之后跟zyf商量半天总算搞懂了。
首先随便找一个4*4满足条件的矩阵来,我用的下面这个:
这个其实用了下面的一个结论,在PS当中。
0 1 2 3
4 5 6 7
8 9 10 11
12 13 14 15
考虑这样一个东西:
a^b=(a+c)^(b+c)的条件是什么?
答案是c>a&&c>b
实际上如果c>a,那么a+c只会在原来a为0的二进制位上作出更改,而在偶数次异或之后异或和会变为0
例如:a^a=0,a^a^a^a=0
所以把4*4的矩阵不断重复,每次加上16、32、48即可
下面的get函数是用来获得某个点的编号的,类似于n行n列的矩阵,a[i][j]前面一共有i*n+j个元素(i,j从0开始)
真就数据结构期末考试呗。
代码:
#include <bits/stdc++.h> #define int long long #define sc(a) scanf("%lld",&a) #define scc(a,b) scanf("%lld %lld",&a,&b) #define sccc(a,b,c) scanf("%lld %lld %lld",&a,&b,&c) #define schar(a) scanf("%c",&a) #define pr(a) printf("%lld",a) #define fo(i,a,b) for(int i=a;i<b;++i) #define re(i,a,b) for(int i=a;i<=b;++i) #define rfo(i,a,b) for(int i=a;i>b;--i) #define rre(i,a,b) for(int i=a;i>=b;--i) #define prn() printf("\n") #define prs() printf(" ") #define mkp make_pair #define pii pair<int,int> #define pub(a) push_back(a) #define pob() pop_back() #define puf(a) push_front(a) #define pof() pop_front() #define fst first #define snd second #define frt front() #define bak back() #define mem0(a) memset(a,0,sizeof(a)) #define memmx(a) memset(a,0x3f3f,sizeof(a)) #define memmn(a) memset(a,-0x3f3f,sizeof(a)) #define debug #define db double #define yyes cout<<"YES"<<endl; #define nno cout<<"NO"<<endl; using namespace std; typedef vector<int> vei; typedef vector<pii> vep; typedef map<int,int> mpii; typedef map<char,int> mpci; typedef map<string,int> mpsi; typedef deque<int> deqi; typedef deque<char> deqc; typedef priority_queue<int> mxpq; typedef priority_queue<int,vector<int>,greater<int> > mnpq; typedef priority_queue<pii> mxpqii; typedef priority_queue<pii,vector<pii>,greater<pii> > mnpqii; const int maxn=500005; const int inf=0x3f3f3f3f3f3f3f3f; const int MOD=100000007; const db eps=1e-10; int qpow(int a,int b){int tmp=a%MOD,ans=1;while(b){if(b&1){ans*=tmp,ans%=MOD;}tmp*=tmp,tmp%=MOD,b>>=1;}return ans;} int lowbit(int x){return x&-x;} int max(int a,int b){return a>b?a:b;} int min(int a,int b){return a<b?a:b;} int mmax(int a,int b,int c){return max(a,max(b,c));} int mmin(int a,int b,int c){return min(a,min(b,c));} void mod(int &a){a+=MOD;a%=MOD;} bool chk(int now){} int half(int l,int r){while(l<=r){int m=(l+r)/2;if(chk(m))r=m-1;else l=m+1;}return l;} int ll(int p){return p<<1;} int rr(int p){return p<<1|1;} int mm(int l,int r){return (l+r)/2;} int lg(int x){if(x==0) return 1;return (int)log2(x)+1;} bool smleql(db a,db b){if(a<b||fabs(a-b)<=eps)return true;return false;} db len(db a,db b,db c,db d){return sqrt((a-c)*(a-c)+(b-d)*(b-d));} bool isp(int x){if(x==1)return false;if(x==2)return true;for(int i=2;i*i<=x;++i)if(x%i==0)return false;return true;} int n; int ans[1005][1005]; int a[4][4]={0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15}; void out(){ fo(i,0,n){ fo(j,0,n){ cout<<ans[i][j]<<' '; } cout<<endl; } } int get(int i,int j){ return (n/4)*(i/4)+(j/4); } void solve(){ fo(i,0,n){ fo(j,0,n){ ans[i][j]=get(i,j)*16+a[i%4][j%4]; } } } signed main(){ ios_base::sync_with_stdio(0); cin.tie(0),cout.tie(0); cin>>n; solve(); out(); return 0; }
PS:从这儿嗨学了一个结论,4的倍数开始的连续的4个数异或和为0
比如0、1、2、3和8、9、10、11
D、假设这儿有一个n的排列,每个位置上的数字是pi,si表示在i之前比pi小的所有数字之和
现在给定n和si,要你重建pi,保证有解
首先考虑1的位置,假设有这样一个排列:
3 2 5 1 4
它的si数组很容易求出:
0 0 5 0 6
首先,对于1来说,它对应位置上的si一定是0,因为不会有数字比1更小,并且对于所有在1后面的数字,他们的si一定不为0,这意味着最后一个0的位置一定是1
在上例中,首先找到1的位置,并且开始重建pi:
* * * 1 *
随后把1位置上的si设为无穷,并且把1位置后面所有的si减1,这一步可以用线段树维护住,si如图:
0 0 5 inf 5
此时找2的位置,很显然,在1消失之后,2成为了最小的数字,此时最后一个0的位置就是2的位置,重复上述操作。
pi:* 2 * 1 *
si:0 inf 3 inf-2 3
算法到这儿已经很明确了,用线段树维护住si的值,从1到n往回填充数字。
下面的问题是如何logn找到最后一个0的位置,利用线段树二分向下查找即可,每一次先看右侧的最小值是否是0,如果不是,向左查找,这样一定可以找到最靠右的0的位置。
写的时候下传标记写锅了,我居然只在标记等于0的时候才下传,以后还是少用!a来判断a是否等于0,多用==
代码:
#include <bits/stdc++.h> #define int long long #define sc(a) scanf("%lld",&a) #define scc(a,b) scanf("%lld %lld",&a,&b) #define sccc(a,b,c) scanf("%lld %lld %lld",&a,&b,&c) #define schar(a) scanf("%c",&a) #define pr(a) printf("%lld",a) #define fo(i,a,b) for(int i=a;i<b;++i) #define re(i,a,b) for(int i=a;i<=b;++i) #define rfo(i,a,b) for(int i=a;i>b;--i) #define rre(i,a,b) for(int i=a;i>=b;--i) #define prn() printf("\n") #define prs() printf(" ") #define mkp make_pair #define pii pair<int,int> #define pub(a) push_back(a) #define pob() pop_back() #define puf(a) push_front(a) #define pof() pop_front() #define fst first #define snd second #define frt front() #define bak back() #define mem0(a) memset(a,0,sizeof(a)) #define memmx(a) memset(a,0x3f3f,sizeof(a)) #define memmn(a) memset(a,-0x3f3f,sizeof(a)) #define debug #define db double #define yyes cout<<"YES"<<endl; #define nno cout<<"NO"<<endl; using namespace std; typedef vector<int> vei; typedef vector<pii> vep; typedef map<int,int> mpii; typedef map<char,int> mpci; typedef map<string,int> mpsi; typedef deque<int> deqi; typedef deque<char> deqc; typedef priority_queue<int> mxpq; typedef priority_queue<int,vector<int>,greater<int> > mnpq; typedef priority_queue<pii> mxpqii; typedef priority_queue<pii,vector<pii>,greater<pii> > mnpqii; const int maxn=1000005; const int inf=0x3f3f3f3f3f3f3f3f; const int MOD=100000007; const db eps=1e-10; int qpow(int a,int b){int tmp=a%MOD,ans=1;while(b){if(b&1){ans*=tmp,ans%=MOD;}tmp*=tmp,tmp%=MOD,b>>=1;}return ans;} int lowbit(int x){return x&-x;} int max(int a,int b){return a>b?a:b;} int min(int a,int b){return a<b?a:b;} int mmax(int a,int b,int c){return max(a,max(b,c));} int mmin(int a,int b,int c){return min(a,min(b,c));} void mod(int &a){a+=MOD;a%=MOD;} bool chk(int now){} int half(int l,int r){while(l<=r){int m=(l+r)/2;if(chk(m))r=m-1;else l=m+1;}return l;} int ll(int p){return p<<1;} int rr(int p){return p<<1|1;} int mm(int l,int r){return (l+r)/2;} int lg(int x){if(x==0) return 1;return (int)log2(x)+1;} bool smleql(db a,db b){if(a<b||fabs(a-b)<=eps)return true;return false;} db len(db a,db b,db c,db d){return sqrt((a-c)*(a-c)+(b-d)*(b-d));} bool isp(int x){if(x==1)return false;if(x==2)return true;for(int i=2;i*i<=x;++i)if(x%i==0)return false;return true;} int n,s[maxn],ans[maxn]; int tr[maxn],tag[maxn]; void up(int p){tr[p]=min(tr[ll(p)],tr[rr(p)]);} void down(int p){ if(tag[p]){ tr[ll(p)]+=tag[p]; tr[rr(p)]+=tag[p]; tag[ll(p)]+=tag[p]; tag[rr(p)]+=tag[p]; tag[p]=0; } } void build(int p,int l,int r){ if(l==r){ tr[p]=s[l]; return; } int m=mm(l,r); build(ll(p),l,m); build(rr(p),m+1,r); up(p); } int q(int p,int l,int r,int pos){ if(l==r&&l==pos) return tr[p]; int m=mm(l,r); down(p); int ans; if(pos<=m) ans=q(ll(p),l,m,pos); else ans=q(rr(p),m+1,r,pos); up(p); return ans; } void change(int p,int l,int r,int L,int R,int v){ if(L<=l&&r<=R){ tr[p]+=v; tag[p]+=v; return; } int m=mm(l,r); down(p); if(L<=m) change(ll(p),l,m,L,R,v); if(R>m) change(rr(p),m+1,r,L,R,v); up(p); } int pos(int p,int l,int r){ if(l==r) return l; int res=-1; int m=mm(l,r); down(p); if(tr[rr(p)]==0) res=pos(rr(p),m+1,r); else res=pos(ll(p),l,m); up(p); return res; } signed main(){ ios_base::sync_with_stdio(0); cin.tie(0),cout.tie(0); cin>>n; re(i,1,n) cin>>s[i]; memmx(tr); build(1,1,n); re(i,1,n){ int p=pos(1,1,n); // re(j,1,n) cout<<q(1,1,n,j)<<" \n"[j==n]; ans[p]=i; if(p!=n) change(1,1,n,p+1,n,-i); change(1,1,n,p,p,inf); } re(i,1,n) cout<<ans[i]<<' '; return 0; } /* 5 0 1 1 1 10 */