BZOJ 3329 Xorequ
题面
Description
Input
第一行一个正整数,表示数据组数据 ,接下来T行
每行一个正整数N
Output
2T行
第2i-1行表示第i个数据中问题一的解,
第2*i行表示第i个数据中问题二的解,
Sample Input
1
1
Sample Output
1
2
HINT
x=1与x=2都是原方程的根,注意第一个问题的解不要mod 109+7
\(1≤N≤10^{18}\)
\(1≤T≤1000\)
题解
- step 1: 打表;
- step 2: 找规律...
我们发现对于一个数\(x\), 当且仅当\(x\)的二进制表达中没有连续的\(1\)时, \(x\)是方程的根.
所以subtask 1的做法就是数位DP.
至于subtask 2, 我们发现\(cnt(2^x) = F_{x + 1} : {F_x}为斐波那契数列\)
因此矩阵快速幂求斐波那契数列即可.
#include <cstdio>
#include <cstring>
namespace subtask1
{
long long f[60], n;
inline void initialize()
{
memset(f, -1, sizeof(f));
}
long long DFS(int lst, int pos, int bnd)
{
if(! pos)
{
if(bnd)
{
int k = n & 1;
if(k && ! lst)
return 2;
else
return 1;
}
else
return ! lst ? 2 : 1;
}
if(lst == 1)
{
if(bnd)
return DFS(0, pos - 1, n >> pos & 1 ^ 1);
else
return DFS(0, pos - 1, 0);
}
else if(lst == 0)
{
if(! bnd)
return ~ f[pos] ? f[pos] : f[pos] = DFS(1, pos - 1, 0) + DFS(0, pos - 1, 0);
else
{
int k = n >> pos & 1;
if(k == 1)
return DFS(0, pos - 1, 0) + DFS(1, pos - 1, 1);
else
return DFS(0, pos - 1, 1);
}
}
}
inline long long work(long long _n)
{
n = _n;
return DFS(0, 59, 1) - 1;
}
}
namespace subtask2
{
const int MOD = (int)1e9 + 7;
struct matrix
{
int n, m;
int a[2][2];
inline matrix(int _n, int _m)
{
n = _n, m = _m;
}
inline matrix friend operator *(const matrix &a, const matrix &b)
{
matrix res(a.n, b.m);
memset(res.a, 0, sizeof(res.a));
for(int i = 0; i < a.n; ++ i)
for(int j = 0; j < b.m; ++ j)
for(int k = 0; k < a.m; ++ k)
res.a[i][j] = (res.a[i][j] + (long long)a.a[i][k] * b.a[k][j]) % MOD;
return res;
}
};
inline int work(long long n)
{
matrix A(2, 2);
for(int i = 0; i < 2; ++ i)
for(int j = 0; j < 2; ++ j)
A.a[i][j] = i || j;
matrix res(2, 2);
for(int i = 0; i < 2; ++ i)
for(int j = 0; j < 2; ++ j)
res.a[i][j] = i == j;
for(; n; A = A * A, n >>= 1)
if(n & 1)
res = res * A;
return (res.a[1][0] + res.a[1][1]) % MOD;
}
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("BZOJ3329.in", "r", stdin);
#endif
subtask1::initialize();
int T;
for(scanf("%d", &T); T; -- T)
{
long long n;
scanf("%lld", &n);
printf("%lld\n%d\n", subtask1::work(n), subtask2::work(n));
}
}