51nod难题系列新代码来啦
普通代码:
#include<cstdio>
typedef long long ll;
const int MOD = int(1E9) + 7;
const int MSIZE = 64;
int pow_mod(int b, int p) {
int ret = 1;
while( p ) {
if( p & 1 ) ret = 1LL*ret*b%MOD;
b = 1LL*b*b%MOD;
p >>= 1;
}
return ret;
}
int len;
struct poly{
int k[2*MSIZE + 5];
poly() {for(int i=0;i<=2*MSIZE;i++) k[i] = 0;}
int get_val(int x) {
int ret = 0;
for(int i=len;i>=0;i--)
ret = (1LL*ret*x%MOD + k[i])%MOD;
return ret;
}
friend poly operator +(poly A, poly B) {
poly C;
for(int i=0;i<MSIZE;i++)
C.k[i] = (A.k[i] + B.k[i])%MOD;
return C;
}
friend poly operator -(poly A, poly B) {
poly C;
for(int i=0;i<MSIZE;i++)
C.k[i] = (A.k[i] + MOD - B.k[i])%MOD;
return C;
}
friend poly operator *(int k, poly B) {
poly C;
for(int i=0;i<MSIZE;i++)
C.k[i] = 1LL*k*B.k[i]%MOD;
return C;
}
friend poly mul_mod(poly A, poly B, poly C) {
poly D;
for(int i=0;i<=2*len;i++)
for(int j=0;j<=i;j++)
D.k[i] = (D.k[i] + 1LL*A.k[j]*B.k[i-j]%MOD)%MOD;
for(int i=2*len;i>=len;i--) {
for(int j=0;j<=len;j++)
D.k[i-len+j] = (D.k[i-len+j] + MOD - 1LL*D.k[i]*C.k[j]%MOD)%MOD;
}
return D;
}
void debug() {
for(int i=0;i<2*MSIZE;i++)
printf("%d ", k[i]);
puts("");
}
}pw[MSIZE + 5], a[MSIZE + 5];
int comb[MSIZE + 5][MSIZE + 5];
void init() {
for(int i=0;i<MSIZE;i++) {
comb[i][0] = 1;
for(int j=1;j<=i;j++)
comb[i][j] = (comb[i-1][j] + comb[i-1][j-1])%MOD;
}
for(int i=0;i<MSIZE;i++) {
for(int j=0;j<=i+1;j++)
pw[i].k[j] = comb[i+1][j];
for(int j=0;j<i;j++)
pw[i] = (pw[i] - comb[i+1][j]*pw[j]);
pw[i] = 1LL*pow_mod(i+1, MOD-2)*pw[i];
}
for(int i=0;i<MSIZE;i++)
for(int j=0;j<=i+1;j++)
for(int k=0;k<=j;k++)
a[i].k[k] = (a[i].k[k] + 1LL*pw[i].k[j]*(1LL*comb[j][k]*(1LL*pow_mod(2, k)*pow_mod(MOD-1, j-k)%MOD)%MOD)%MOD)%MOD;
}
int get_pw(ll x, int k) {return pw[k].get_val(x%MOD);}
int get_pw(ll l, ll r, int k) {return (get_pw(r, k) + MOD - get_pw(l - 1, k))%MOD;}
int get_val(poly A, ll l, ll r) {
int ret = 0;
for(int i=0;i<len;i++)
ret = (ret + 1LL*get_pw(l, r, i)*A.k[i]%MOD)%MOD;
return ret;
}
poly trans(poly A, ll r) {
poly B; B.k[0] = get_val(A, 0, r);
for(int i=0;i<len;i++)
B = B - A.k[i]*a[i];
return B;
}
poly get_M(ll n) {
poly A, B, M; B.k[0] = M.k[len] = 1;
for(int i=0;i<len;i++,n/=2){
int sA = get_val(A, 1, n/2), sB = get_val(B, n/2 + 1, n);
M.k[len-i-1] = (MOD - (sA + sB)%MOD)%MOD;
A = trans(A, n/2), A.k[0] = (A.k[0] + sB)%MOD;
B = trans(B, n);
}
return M;
}
poly p_pow(poly M, ll p) {
poly ret, b; b.k[1] = 1, ret.k[0] = 1;
while( p ) {
if( p & 1 ) ret = mul_mod(ret, b, M);
b = mul_mod(b, b, M);
p >>= 1;
}
return ret;
}
int solve(ll n, ll m) {
ll tmp = n; for(len = 0; tmp; len++, tmp /= 2);
return p_pow(get_M(n), m+len-1).k[len-1];
}
int main() {
init(); int T; scanf("%d", &T);
for(int i=1;i<=T;i++) {
ll n, m; scanf("%lld%lld", &n, &m);
printf("%d\n", solve(n, m));
}
}
高效代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long s64;
#define rep(i,l,r) for(int i=l;i<=r;++i)
#define per(i,r,l) for(int i=r;i>=l;--i)
const int N=1e6+5,L=61,D=1e9+7;
s64 mi(s64 x,int y=D-2)
{
s64 ans=1;
while(y)
{
if(y&1)ans=ans*x%D;
x=x*x%D;y>>=1;
}
return ans;
}
s64 w[L],dp[L];
s64 x[L],ans[L];
void mul(s64 a[],s64 b[])
{
static s64 tmp[L*2];
memset(tmp,0,sizeof(tmp));
rep(i,0,L-1)
rep(j,0,L-1)(tmp[i+j]+=a[i]*b[j])%=D;
per(i,2*L-2,L)
{
s64 x=tmp[i];
rep(j,1,L-1)(tmp[i-j]+=x*w[j])%=D;
}
memcpy(a,tmp,sizeof(x));
}
namespace GET_W
{
s64 w[L][L],dp[L];
void trans(int i)
{
per(j,i,0)
{
s64 ans=0;
rep(k,0,j)(ans+=dp[k]*w[i-k][j-k])%=D;
dp[j]=ans;
}
}
void init()
{
rep(i,0,L-1)
{
w[i][i]=1;
rep(j,0,i-1)
{
s64 ans=0;
rep(k,0,j)(ans+=w[i-1][k]*w[i-1-k][j-k])%=D;
w[i][j]=ans;
}
}
}
void work(s64 n)
{
n*=2;
int i=0;
while(!((n>>i)&1))++i;
memcpy(dp,w[i],sizeof(dp));
while(++i<L)
if((n>>i)&1)trans(i);
rep(i,0,L-1)::w[i]+=dp[i];
}
};
void work()
{
s64 n,m;
cin>>n>>m;
memset(w,0,sizeof(w));
GET_W::work(n/2);
rep(i,0,L-1)w[i]=-w[i];
GET_W::work(n);
dp[0]=1;
rep(i,1,L-1)
{
dp[i]=0;
rep(j,0,i-1)(dp[i]+=dp[j]*w[i-j])%=D;
}
memset(x,0,sizeof(x));
x[1]=1;
--m;
memcpy(ans,x,sizeof(ans));
while(m)
{
if(m&1)mul(ans,x);
mul(x,x);m>>=1;
}
s64 Ans=0;
rep(i,0,L-1)(Ans+=ans[i]*dp[i])%=D;
printf("%d\n",int((Ans%D+D)%D));
}
int main()
{
#ifdef kcz
freopen("1.in","r",stdin);
#endif
GET_W::init();
int tt;
cin>>tt;
while(tt--)work();
}
喜欢就给个赞吧(记得关注)