[BZOJ3329] Xorequ

题解:

网上的方法基本是建立在发现临位不能相等的基础上的

这个很好证。。

但是不利用这个特征也是可以的

x^2x=3x

我们考虑二进制的前i位,我们会发现3x最多涉及到了前i+2位

于是我们可以记录一下前i位的3x的i+1,i+2位的状态,以及第i位填了什么

因为后面的位置是不影响前面的位置的,所以前面必须要匹配

然后这个东西数位dp一下(数位dp正着做反着做其实也差不多)

这个dp只要你头脑清醒还是比较好打的。。。。

对于第二问这种东西很明显是找规律

fib数列,用正解很容易证明,矩阵求一下就好

代码:

 

#include <bits/stdc++.h>
using namespace std;
#define rint register ll
#define IL inline
#define rep(i,h,t) for (rint i=h;i<=t;i++)
#define dep(i,t,h) for (rint i=t;i>=h;i--)
#define ll long long
const ll mo=1e9+7;
ll n,v[100],f[100][4][2][2];
struct re{
  ll a[2][2];
  re() { a[0][0]=a[0][1]=a[1][0]=a[1][1]=0;};
}now;
re js(re x,re y)
{
  re a;
  rep(i,0,1)
    rep(j,0,1)
      rep(k,0,1)
        a.a[i][k]+=x.a[i][j]*y.a[j][k],a.a[i][k]%=mo;
  return(a); 
}
re fsp(ll x)
{
  if (x==1) return(now);
  re k1=fsp(x/2);
  k1=js(k1,k1);
  if (x%2) k1=js(k1,now);
  return(k1);
}
int main()
{
  freopen("1.in","r",stdin);
  freopen("1.out","w",stdout);
  ios::sync_with_stdio(false);
  ll T;
  now.a[0][0]=1; now.a[0][1]=1;
  now.a[1][0]=1; now.a[1][1]=0;
  cin>>T;
  rep(kk,1,T)
  {
  memset(f,0,sizeof(f));
  cin>>n;
  ll l=0,tmp=n;
  while (tmp) l++,v[l]=tmp%2,tmp/=2;
  f[0][0][0][0]=1; 
  rep(i,1,l)
  {
    if (v[i]==1)
    {
      f[i][3][1][1]=f[i-1][3][1][1];
      f[i][3][1][0]=f[i-1][3][1][0];
      f[i][2][1][1]=f[i-1][2][0][1];
      f[i][2][1][0]=f[i-1][2][0][0];
      f[i][1][1][1]=f[i-1][0][0][1];
      f[i][1][1][0]=f[i-1][0][0][0];
      f[i][1][0][0]=f[i-1][3][1][0]+f[i-1][3][1][1]
                    +f[i-1][2][0][1]+f[i-1][2][0][0];
      f[i][0][0][0]=f[i-1][1][1][0]+f[i-1][1][1][1]
                    +f[i-1][0][0][0]+f[i-1][0][0][1];
    } else
    {
      f[i][3][1][1]=f[i-1][3][1][1]+f[i-1][3][1][0];
      f[i][2][1][1]=f[i-1][2][0][1]+f[i-1][2][0][0];
      f[i][1][1][1]=f[i-1][0][0][1]+f[i-1][0][0][0];
      f[i][1][0][0]=f[i-1][3][1][0]+f[i-1][2][0][0];
      f[i][1][0][1]=f[i-1][3][1][1]+f[i-1][2][0][1];
      f[i][0][0][0]=f[i-1][1][1][0]+f[i-1][0][0][0];
      f[i][0][0][1]=f[i-1][1][1][1]+f[i-1][0][0][1];
    }
  }
  cout<<f[l][1][1][0]+f[l][0][0][0]-1<<endl;
  cout<<fsp(n+1).a[0][0]<<endl;
  }
  return 0; 
}

 

posted @ 2018-09-17 21:52  尹吴潇  阅读(212)  评论(0编辑  收藏  举报