bzoj 3329: Xorequ

传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=3329
思路:根据xor的性质,分析出二进制表示下1是不能相邻的,数位dp和矩阵加速就好
犯了很多低级错误,比如取模和多组数据的清空,可以AFO了,,,,
代码:

#include<iostream>
#include<cstring>
#include<cstdio>
#include<string>
#define N 100
using namespace std;
typedef long long LL;
struct node { LL g[5][5];};
LL n,ans1,ans2,f[N + 5][2],P,top,m,st[N + 5];
node a;
inline LL getnum(){
    LL num; char c;
    while (!isdigit(c = getchar()));
    num = c - '0';
    while (isdigit(c = getchar())) num = 10 * num + c - '0';
    return num;
}

inline void init(){
    f[1][0] = f[1][1] = 1; P = 1000000007LL;
    for (int i = 2;i <= N; ++i){
      f[i][0] = f[i - 1][0] + f[i - 1][1];
      f[i][1] = f[i - 1][0];}
    a.g[1][1] = 1; a.g[1][2] = 1;
    a.g[2][1] = 1; a.g[2][2] = 0;
}

inline node mul(node a,node b){
    node c;
    memset(c.g,0,sizeof(c.g));
    for (int k = 1;k <= 2; ++k)
      for (int i = 1;i <= 2; ++i)
        for (int j = 1;j <= 2;++j)
          c.g[i][j] = (c.g[i][j] + a.g[i][k] * b.g[k][j]%P)%P;
   return c;
}

inline void make_it(){
    node base = a,r;
    memset(r.g,0,sizeof(r.g));
    r.g[1][1] = r.g[2][2] = 1;
    for (;n;n >>= 1){
        if (n & 1) r = mul(r,base);
        base = mul(base,base);
    }
    ans2 =  (r.g[1][1] + r.g[1][2] + r.g[2][1] + r.g[2][2])%P;
}

inline void DO_IT(){
    top = 0; ans1 = -1; ans2 = 0; bool flag = 1;
    n = m = getnum();
    memset(st,0,sizeof(st));
    if (!n) { ans1 = 0; ans2 = 1;}
    else{
    while (m) st[++top] = m & 1,m >>= 1;
    for (int i = top;i > 1; --i){
     if (st[i]) ans1 += f[i][0];
     if (st[i]&st[i + 1]) { flag = 0;break;} }
     if (flag){
     if (!st[1]||st[1]&&st[2]) ans1++;
     else ans1 += 2; }
    n--;
    make_it();}  
}

int main(){
    int T;
    init();
    T = getnum();
    while (T--){
      DO_IT();
      printf("%lld\n%lld\n",ans1,ans2);
    }
    return 0;
}

你可能感兴趣的:(bzoj 3329: Xorequ)