题意:
数据范围:
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)n−xn。当
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;
}