二进制专场,还被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
*/
来源:oschina
链接:https://my.oschina.net/u/4312979/blog/3405542