数 位 D P 开 long long
首先第一问是转化。
于是就可以二进制下DP了。
第二问是递推,假设最后$n-1$个01位的填法设为$f[i-1]$(方案包括0),于是有fib数列递推关系(很好推),然后矩阵快速幂即可。
一开始思路有点乱,导致边界初始化屡次出错。
WA1:见标题赤字。
WA2:初始化写错了。。。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<cmath> 6 #define dbg(x) cerr << #x << " = " << x <<endl 7 using namespace std; 8 typedef long long ll; 9 typedef double db; 10 typedef pair<int,int> pii; 11 template<typename T>inline T _min(T A,T B){return A<B?A:B;} 12 template<typename T>inline T _max(T A,T B){return A>B?A:B;} 13 template<typename T>inline char MIN(T&A,T B){return A>B?(A=B,1):0;} 14 template<typename T>inline char MAX(T&A,T B){return A<B?(A=B,1):0;} 15 template<typename T>inline void _swap(T&A,T&B){A^=B^=A^=B;} 16 template<typename T>inline T read(T&x){ 17 x=0;int f=0;char c;while(!isdigit(c=getchar()))if(c=='-')f=1; 18 while(isdigit(c))x=x*10+(c&15),c=getchar();return f?x=-x:x; 19 } 20 ll f[65][2];//mistake:long long 21 int T,b[65]; 22 ll n;//mistake:long long 23 ll dp(int len,int las,int limit){ 24 if(!len)return 1; 25 if(!limit&&~f[len][las])return f[len][las]; 26 int num=limit?b[len]:1;ll ret=0; 27 for(register int i=0;i<=num;++i) 28 ret+=las?(i?0:dp(len-1,0,limit&&i==num)):dp(len-1,i,limit&&i==num); 29 return limit?ret:f[len][las]=ret; 30 } 31 inline ll task1(ll x){ 32 int len=0;while(x)b[++len]=x&1,x>>=1; 33 return dp(len,0,1)-1; 34 } 35 const int P=1e9+7; 36 struct matrix{ 37 int a[2][2]; 38 matrix(){a[0][0]=a[1][1]=1,a[0][1]=a[1][0]=0;} 39 inline void build(){a[0][0]=0,a[0][1]=a[1][0]=a[1][1]=1;} 40 inline matrix operator *(const matrix&A)const{ 41 matrix B; 42 B.a[0][0]=(a[0][0]*1ll*A.a[0][0]+a[0][1]*1ll*A.a[1][0])%P; 43 B.a[0][1]=(a[0][0]*1ll*A.a[0][1]+a[0][1]*1ll*A.a[1][1])%P; 44 B.a[1][0]=(a[1][0]*1ll*A.a[0][0]+a[1][1]*1ll*A.a[1][0])%P; 45 B.a[1][1]=(a[1][0]*1ll*A.a[0][1]+a[1][1]*1ll*A.a[1][1])%P; 46 return B; 47 } 48 inline void operator *=(const matrix&A){*this=*this * A;} 49 }; 50 inline int task2(ll p){ 51 if(p==1)return 2; 52 if(p==2)return 3; 53 matrix ret,x;x.build();p-=2; 54 for(;p;p>>=1,x*=x)if(p&1)ret*=x; 55 return (ret.a[1][1]*1ll*3+ret.a[0][1]*1ll*2)%P; 56 } 57 58 int main(){//freopen("test.in","r",stdin);freopen("test.ans","w",stdout); 59 memset(f,-1,sizeof f); 60 read(T);while(T--)read(n),printf("%lld\n%d\n",task1(n),task2(n)); 61 return 0; 62 }