JZOJ5973. 【清华2019冬令营模拟12.8】序列

15 篇文章 0 订阅

题意:

数据范围:

Analysis:

这种东西一般比较套路啦,复杂度看起来也是 log ⁡ \log log的。
第一种操作发现只要模拟操作递归就好,每次大小减半,复杂度 O ( log ⁡ n ) O(\log{n}) O(logn)
我们考虑从 n 2 \frac{n}{2} 2n推到 n n n
我们发现奇数的情况可以写成: ( − 1 ) n − x n (-1)^n{-}x_n (1)nxn。当 n n n为奇数的时候会和 x 2 n x_{2n} x2n抵消。
我们只用考虑偶数的 x x x即可。偶数的 x x x会算两遍,我们可以从 n 2 \frac{n}{2} 2n的偶数推到当前的答案和。会发现数值上就是乘 2 2 2,也就是取负数即可。
我们如何得到 n n n的偶数的和,发现就是 n 2 \frac{n}{2} 2n的答案取个负。
n n n为奇数,还要加上当前的 n n n,这个可以用一个 log ⁡ \log log来搞,随意想想貌似也能 O ( 1 ) O(1) O(1)
于是这题就没了。

Code:

# include<cstdio>
# include<cstring>
# include<algorithm>
using namespace std;
typedef long long ll;
struct node
{ ll x,y; };
int q;
ll n;
inline int calc(ll n)
{
	if (n == 1) return 1;
	if (n & 1) return (((n + 1) >> 1) & 1) ? calc((n + 1) >> 1) : -calc((n + 1) >> 1);
	else return -calc(n >> 1);
}
inline node S(ll n)
{
	if (n == 1) return (node){1ll,0ll};
	node now = S(n >> 1); int v = 0;
	if (n & 1) v = calc(n);
	return (node){now.y * -2ll + v,-now.x};
}
int main()
{
	freopen("sequence.in","r",stdin);
	freopen("sequence.out","w",stdout);
	scanf("%d",&q);
	while (q--)
	{
		int opt; scanf("%d%lld",&opt,&n);
		if (opt == 1) printf("%d\n",calc(n));
		else
		{
			node ans = S(n);
			printf("%lld\n",ans.x);
		}
	}
	return 0;
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值