题意
求长度为 n n n的数字串方案数,满足奇数位和等于偶数位和,且是回文串
题解
首先考虑
n
n
n为偶数,此时左侧和右侧奇偶性相反,所以必然奇数和偶数的和相等。
n
n
n为奇数的时候:
枚举中间位是
k
k
k,且接下来的奇数偶数不考虑中间这一位。
【注意这里的
k
k
k,由于回文串,奇数和和偶数和都是偶数,所有差一定也是偶数】
如果中间是奇数,偶数
=
=
= 奇数
+
k
+k
+k
反之,奇数
=
=
= 偶数
+
k
+k
+k
显然前者的时候,奇数和偶数是一样的,所以我们可以都变成第二个问题。
奇数
−
-
− 偶数
=
k
=k
=k
显然这样计算方案数,我们仍然要考虑奇数和偶数,而这样是很难计算的。
如果我们能把
−
-
−变成
+
+
+,就可以只考虑如何放数了。
做法就是,奇数
+
+
+((
9
−
9-
9−偶数)和)
=
k
+
9
=k+9
=k+9的和
就是把每个偶数位
x
x
x变成
9
−
x
9-x
9−x,这样
−
x
-x
−x就是
+
x
−
9
+x-9
+x−9了,转换成了加法。
也就是转换成了
∑
x
i
=
k
+
e
v
e
n
∗
9
=
m
\sum x_i=k+even*9=m
∑xi=k+even∗9=m
前一半和后一半一样,所以我们只用考虑前一半的数,
n
=
n
2
,
m
=
m
2
n=\frac{n}{2},m=\frac{m}{2}
n=2n,m=2m,
把一个
1
1
1当作一个小球,一位当作一个盒子,就是允许空盒的放小球方案数了,我们用隔板法,
C
(
m
+
n
−
1
,
n
−
1
)
C(m+n-1,n-1)
C(m+n−1,n−1)即方案数,但是有些情况某些位会超过
9
9
9,这就需要容斥了。
我们枚举超过的位数,
a
n
s
=
∑
(
−
1
)
i
C
(
n
,
i
)
∗
C
(
M
−
10
∗
i
+
n
−
1
,
n
−
1
)
ans=\sum(-1)^iC(n,i)*C(M-10*i+n-1,n-1)
ans=∑(−1)iC(n,i)∗C(M−10∗i+n−1,n−1)即总方案数。
超过的位数为
i
i
i时,方案数即:我们将
i
i
i个盒子挑出来,都放上
10
10
10,这样就算之后空盒也是保证超过的,
m
m
m去掉
10
∗
i
10*i
10∗i,然后继续放带空盒的方案,就可以得到答案了。
#pragma GCC optimize(2)
#pragma GCC optimize("Ofast")
#pragma GCC target("sse3","sse2","sse")
//#pragma GCC target("avx","sse4","sse4.1","sse4.2","ssse3")
//#pragma GCC target("f16c")
//#pragma GCC target("fma","avx2")
//#pragma GCC target("xop","fma4")
#pragma GCC optimize("inline","fast-math","unroll-loops","no-stack-protector")
#pragma GCC diagnostic error "-fwhole-program"
#pragma GCC diagnostic error "-fcse-skip-blocks"
#pragma GCC diagnostic error "-funsafe-loop-optimizations"
#pragma GCC diagnostic error "-std=c++14"
#include<bits/stdc++.h>
#define FOR(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
typedef long long ll;
const int maxn = 6e6+1000;
const ll mod = 1e9 + 7;
ll F[maxn],Finv[maxn],inv[maxn];
inline ll quick_pow(ll x,int p){
ll res=1;
while(p){
if(p&1)res=(res*x)%mod;
x=(x*x)%mod, p>>=1;
}
return res;
}
void init(){
F[0]=Finv[0]=inv[1]=1ll;
for(int i=2;i<maxn;i++){
inv[i]=1ll*(mod-mod/i)*inv[mod%i]%mod;
}
for(int i=1;i<maxn;i++){
F[i]=F[i-1]*i%mod;
Finv[i]=Finv[i-1]*inv[i]%mod;
}
}
ll C(ll n,ll m){
if(m<0||m>n)return 0;
return F[n]*1ll*Finv[n-m]%mod*Finv[m]%mod;
}
int main(){
int n;cin>>n;
init();
if(n%2==0)return printf("%lld\n",quick_pow(10,n/2)),0;
int odd=(n+1)/2,even=n/2;
if(((n+1)/2)%2)odd--;
else even--;
ll m=even*9,ans=0;
odd/=2,even/=2;
for(int k=0;k<10;k++){
ll tmp=(m+k)/2,res=0;
if(k%2)continue;
for(int i=0,n=odd+even;i<=n;i++){
if(i%2)res=(res-C(n,i)*C(tmp-10*i+n-1,n-1))%mod;
else res=(res+C(n,i)*C(tmp-10*i+n-1,n-1))%mod;
res=(res+mod)%mod;
}
ans=(ans+res)%mod;
}
cout<<ans<<endl;
}