列表

详情


NC229191. 依久依久

描述

传说中,小喵和小矣是一对夫妻,他们关系很和洽。由于两位都是数学系毕业的,所以平日里他们经常一起研究数学。

最近,他们发现,一个数不仅可以被若干个不同的二进制分解,还可以被若干个斐波那契数分解!
这里定义 ,对于
但很快,他们发现分解方式并不唯一,不过只要满足分解成的斐波那契数不相邻,那么就有了唯一分解。形式化地。设 ,满足 ,则此为 的唯一分解。
例如 ,那么 ,因此
小喵定义 表示 ,即分解的斐波那契数的异或和。
小矣紧接着想知道,如果给定 ,那么 的值是多少呢?
由于小矣脑子里有许多疑惑,所以他会询问你很多次。

本场比赛大样例 :https://uploadfiles.nowcoder.com/files/20211016/%E5%A4%A7%E6%A0%B7%E4%BE%8B.zip

输入描述

第一行,输入查询组数 
接下来 行,每行输入两个数

输出描述

输出共  行,每行输出相应的异或和。

示例1

输入:

3
20 30
114 514
114514 1919810

输出:

15
142
792192

说明:

对于第一组询问,从 x=20\sim 30\text{val} 值依次是 \text{10,21,20,23,22 ,23,16,17,18,29,28} ,异或和为 {15}

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++(g++ 7.5.0) 解法, 执行用时: 1762ms, 内存消耗: 89344K, 提交时间: 2023-04-08 22:53:39

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

ll fib[95];
int len;

map<ll, ll> mp;

ll solve(ll n) {
	if (n <= 0) return 0;
	if (mp.count(n)) return mp[n];
	ll ans = 0;
	for (int i = len; i >= 1; i--) {
		if (n >= fib[i]) {
			if ((n - fib[i] + 1) & 1) ans ^= fib[i];
			return mp[n] = ans ^ solve(n - fib[i]) ^ solve(fib[i] - 1);
		}
	}
	return 0;
}

int main() {
	fib[1] = 1, fib[2] = 2;
	for (int i = 3; i <= 90; ++ i) {
		fib[i] = fib[i - 1] + fib[i - 2];
		if (fib[i] > 1e18) {
			len = i;
			break;
		}
	}
	int T;
	scanf("%d", &T);
	while (T--) {
		ll l, r;
		scanf("%lld%lld", &l, &r);
		printf("%lld\n", solve(r) ^ solve(l - 1));
	}
	return 0;
}

C++ 解法, 执行用时: 2032ms, 内存消耗: 87928K, 提交时间: 2021-10-18 14:37:55

#include<bits/stdc++.h>
using namespace std;
#define ll long long
ll t,fib[109];
map <ll,ll> f;
inline ll solve(ll x)
{
	if(f.find(x)!=f.end()) return f[x];
	ll v=*(upper_bound(fib+1,fib+87+1,x)-1);
	f[x]=solve(v-1)^solve(x-v);
	if((x-v+1)&1) f[x]^=v;
	return f[x];
}
int main()
{
	fib[1]=1,fib[2]=2;
	for(int i=3;i<=87;i++) fib[i]=fib[i-1]+fib[i-2];
	scanf("%lld",&t);
	f[0]=0;
	ll l,r;
	while(t--)
	{
		scanf("%lld%lld",&l,&r);
		printf("%lld\n",solve(l-1)^solve(r));
	}
	return 0;
} 

上一题