下面代码TLE了,但是此题数位dp的思想非常值得学习
Lucas的过程相当于把
n
,
m
n,m
n,m在p进制下的每一位拿出来做组合数
Lucas ( n , m , p ) = ∏ ( n k m k ) m o d p \text{Lucas}(n,m,p)=\prod \dbinom {n_k}{m_k} \bmod p Lucas(n,m,p)=∏(mknk)modp
本题需要求
∑
i
=
1
n
∑
j
=
1
i
[
(
i
j
)
m
o
d
7
=
0
]
\sum_{i=1}^{n}\sum_{j=1}^i[\dbinom {i}{j} \bmod 7=0]
i=1∑nj=1∑i[(ji)mod7=0]
由于 n k , m k n_k,m_k nk,mk都小于7,组合数不可能包含7的,因此想让 ( n m ) m o d 7 = 0 \dbinom {n}{m}\bmod 7=0 (mn)mod7=0 当且仅当 ∏ ( n k m k ) m o d 7 = 0 \prod \dbinom {n_k}{m_k} \bmod 7 =0 ∏(mknk)mod7=0 即存在 n k > m k n_k>m_k nk>mk因为此时 ( n k m k ) = 0 \dbinom {n_k}{m_k}=0 (mknk)=0
#include<bits/stdc++.h>
using namespace std;
const int mod=1e9+7;
using ll=long long;
ll n;
int a[24];
int f[24][2][2][2];
int dfs(int u,int lim1,int lim2,int ok)
{
if(u<=0) return ok;
if(f[u][lim1][lim2][ok]!=-1) return f[u][lim1][lim2][ok];
int v1=lim1?a[u]:6;
f[u][lim1][lim2][ok]=0;
int ans=0;
for(int i=0;i<=v1;i++)
for(int j=0;j<=(lim2?i:6);j++)
ans=(1ll*ans+dfs(u-1,lim1&(i==v1),lim2&(i==j),ok|(i<j)))%mod;
return f[u][lim1][lim2][ok]=ans;
}
int solve(ll x)
{
memset(f,-1,sizeof f);
int cnt=0;
while(x) a[++cnt]=x%7,x/=7;
return dfs(cnt,1,1,0);
}
int main()
{
ios::sync_with_stdio(false);cin.tie();cout.tie(0);
int Tc;
cin>>Tc;
for(int ca=1;ca<=Tc;ca++)
{
cin>>n;
cout<<"Case "<<ca<<": "<<solve(n)<<'\n';
}
return 0;
}