CodeForces - 1339E Perfect Triples(打表找規律)

題目鏈接:點擊查看

題目大意:序列 s 是一個無限數列,現在給出構造方法:

  1. 選擇三個數 a b c ,將其依次加到序列 s 的最後面,三個數需要滿足:
    1. a b c 在序列 s 中均未出現過
    2. a b c 是字典序最小的數列
    3. a ^ b ^ c = 0

現在給出一個 n ( <= 1e16 ) ,求出數列的第 n 項

題目分析:乍一看可能沒什麼思路,不過看起來可以打表,於是打表觀察一下,打表代碼放在最後

打出表後可以發現,以 a b c 爲整體的數對被分成了好幾大段,每一段的長度分別爲 1,4,16,64....4^n,其中在每一大段中,a 都是依次增大的,這是一個比較明顯的規律

因爲這是對於異或的操作,所以將所有數都轉換爲二進制再看一看,會發現 b 和 a 有着某種微妙的關係,仔細觀察觀察或者大膽猜想一下,可以知道這個與四進制有關

將所有數轉換爲四進制後,就能看出 a 與 b 其中的相同位上:

  1. a == 0 時 b =0
  2. a == 1 時 b = 2
  3. a == 2 時 b = 3
  4. a == 3 時 b = 1

這樣就能在知道 n 的基礎上,求出第 n 個數的行與列的座標,然後求出 a 和 b ,根據 a^b^c=0,得到 c=a^b,這樣就能求出答案了

代碼:

AC代碼:

#include<iostream>
#include<cstdio>
#include<string>
#include<ctime>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<stack>
#include<climits>
#include<queue>
#include<map>
#include<set>
#include<sstream>
#include<unordered_map>
using namespace std;

typedef long long LL;

typedef unsigned long long ull;

const int inf=0x3f3f3f3f;

const int N=1e5+100;

const int b[]={0,2,3,1};

LL get_num1(LL x)
{
	LL base=1;
	while(base<x)
	{
		x-=base;
		base<<=2;
	}
	return base+x-1;
}

LL get_num2(LL x)
{
	LL num1=get_num1(x);
	LL ans=0;
	for(int i=0;i<=60;i+=2)
		ans+=(1LL<<i)*b[(num1>>i)%4];
	return ans;
}

int main()
{
#ifndef ONLINE_JUDGE
//	freopen("input.txt","r",stdin);
//	freopen("output.txt","w",stdout);
#endif
//	ios::sync_with_stdio(false);
	int w;
	cin>>w;
	while(w--)
	{
		LL n;
		scanf("%lld",&n);
		LL row=(n-1)/3+1;
		int col=(n-1)%3;
		LL num1=get_num1(row);
		LL num2=get_num2(row);
		LL num3=num1^num2;
		if(col==0)
			printf("%lld\n",num1);
		else if(col==1)
			printf("%lld\n",num2);
		else
			printf("%lld\n",num3);
	}








    return 0;
}

打表代碼:

#include<iostream>
#include<cstdio>
#include<string>
#include<ctime>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<stack>
#include<climits>
#include<queue>
#include<map>
#include<set>
#include<sstream>
#include<unordered_map>
using namespace std;

typedef long long LL;

typedef unsigned long long ull;

const int inf=0x3f3f3f3f;

const int N=1e5+100;

bool vis[N];

void print(int num)//輸出四進制
{
	string ans;
	for(int i=1;i<=5;i++)
	{
		ans+=to_string(num%4);
		num/=4;
	}
	reverse(ans.begin(),ans.end());
	cout<<ans<<' ';
}

int main()
{
#ifndef ONLINE_JUDGE
//	freopen("input.txt","r",stdin);
//	freopen("output.txt","w",stdout);
#endif
//	ios::sync_with_stdio(false);
	for(int k=1;k<=100;k++)
	{
		for(int i=1;i<=1000;i++)
		{
			if(!vis[i])
			{
				for(int j=i+1;j<=1000;j++)
				{
					if(!vis[j]&&!vis[i^j])
					{
						vis[i]=vis[j]=vis[i^j]=true;
						printf("%d %d %d ",i,j,i^j);
						print(i),print(j),print(i^j);
						puts("");
						goto end;
					}
				}
			}
		}
		end:;
	}
	
	
	
	
	
	










    return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章