Codeforces Gym 100725
题解:
先分两种情况, 积为
0
0
与积非, 积为
0
0
的情况容斥求解即可。
考虑积非的情况
令
dp1(i,c2,c3,c5,c7)
d
p
1
(
i
,
c
2
,
c
3
,
c
5
,
c
7
)
表示考虑左边n个数中到第
i
i
个数为止积为的情况数, 枚举下一个数是什么转移即可。
同理令
dp2(i,c2,c3,c5,c7)
d
p
2
(
i
,
c
2
,
c
3
,
c
5
,
c
7
)
表示考虑右边n个数中到第
i
i
个数为止积为的情况数.
最终答案就是
∑c2,c3,c5,c7dp1(n,c2,c3,c5,c7)×dp2(n,c2,c3,c5,c7)
∑
c
2
,
c
3
,
c
5
,
c
7
d
p
1
(
n
,
c
2
,
c
3
,
c
5
,
c
7
)
×
d
p
2
(
n
,
c
2
,
c
3
,
c
5
,
c
7
)
注意在统计最终答案时要用高精度,以及空间限制
64
64
MB需要使用滚动数组。
时间复杂度
O(60n5)
O
(
60
n
5
)
#include<bits/stdc++.h>
#define LL long long
#define ull unsigned long long
#define ULL ull
#define mp make_pair
#define pii pair<int,int>
#define piii pair<int, pii >
#define pll pair <ll,ll>
#define pb push_back
#define big 20160116
#define INF 2147483647
#define pq priority_queue
using namespace std;
inline int read(){
int x=0,f=1;
char ch=getchar();
while (ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();}
while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
namespace Mymath{
LL qp(LL x,LL p,LL mod){
LL ans=1;
while (p){
if (p&1) ans=ans*x%mod;
x=x*x%mod;
p>>=1;
}
return ans;
}
LL inv(LL x,LL mod){
return qp(x,mod-2,mod);
}
LL C(LL N,LL K,LL fact[],LL mod){
return fact[N]*inv(fact[K],mod)%mod*inv(fact[N-K],mod)%mod;
}
template <typename Tp> Tp gcd(Tp A,Tp B){
if (B==0) return A;
return gcd(B,A%B);
}
template <typename Tp> Tp lcm(Tp A,Tp B){
return A*B/gcd(A,B);
}
};
namespace fwt{
using namespace Mymath;
void FWT(int a[],int n,LL mod)
{
for(int d=1;d<n;d<<=1)
for(int m=d<<1,i=0;i<n;i+=m)
for(int j=0;j<d;j++)
{
int x=a[i+j],y=a[i+j+d];
a[i+j]=(x+y)%mod,a[i+j+d]=(x-y+mod)%mod;
//xor:a[i+j]=x+y,a[i+j+d]=x-y;
//and:a[i+j]=x+y;
//or:a[i+j+d]=x+y;
}
}
void UFWT(int a[],int n,LL mod)
{
LL rev=inv(2,mod);
for(int d=1;d<n;d<<=1)
for(int m=d<<1,i=0;i<n;i+=m)
for(int j=0;j<d;j++)
{
int x=a[i+j],y=a[i+j+d];
a[i+j]=1LL*(x+y)*rev%mod,a[i+j+d]=(1LL*(x-y)*rev%mod+mod)%mod;
//xor:a[i+j]=(x+y)/2,a[i+j+d]=(x-y)/2;
//and:a[i+j]=x-y;
//or:a[i+j+d]=y-x;
}
}
void solve(int a[],int b[],int n,LL mod)
{
FWT(a,n,mod);
FWT(b,n,mod);
for(int i=0;i<n;i++) a[i]=1LL*a[i]*b[i]%mod;
UFWT(a,n,mod);
}
};
const int Maxn=55;
string s;
LL dp[2][58][40][21][21];
LL A[58][40][21][21],B[58][40][21][21];
LL p10[19];
LL C(LL n,LL k){
LL ans=1;
for (int i=n;i>=n-k+1;i--){
ans=ans*i/(n+1-i);
}
return ans;
}
int cst[15][15];
const int Maxk=105;
string mul(string a,string b){
int res[Maxk];
memset(res,0,sizeof(res));
reverse(a.begin(),a.end());
reverse(b.begin(),b.end());
for (int i=0;i<a.length();i++){
for (int j=0;j<b.length();j++){
res[i+j]+=(a[i]-'0')*(b[j]-'0');
}
}
for (int i=0;i<Maxk;i++){
if (res[i]>=10) {
res[i+1]+=(res[i]/10);
res[i]%=10;
}
}
string ret;
bool flag=false;
for (int i=Maxk-1;i>=0;i--){
if (flag || res[i]){
flag=true;
ret=ret+(char)(res[i]+'0');
}
}
if (ret=="") ret="0";
return ret;
}
string add(string a,string b){
if (a.length()<b.length()) swap(a,b);
while (a.length()!=b.length()){
b='0'+b;
}
for (int i=a.length()-1;i>=0;i--){
a[i]+=(b[i]-'0');
if (a[i]>'9' && i){
a[i]-=10;
a[i-1]++;
}
}
if (a[0]>'9'){
a[0]-=10;
a='1'+a;
}
return a;
}
string minuss(string a,string b){
//if (a.length()<b.length()) swap(a,b);
while (a.length()!=b.length()){
b='0'+b;
}
for (int i=a.length()-1;i>=0;i--){
a[i]-=(b[i]-'0');
}
for (int i=a.length()-1;i>=0;i--){
if (a[i]<'0'){
a[i]+=10;
a[i-1]--;
}
}
while (a[0]=='0') a=a.substr(1);
return a;
}
string tostr(LL x){
string r;
while (x){
r+=(char)(x%10+'0');
x/=10;
}
reverse(r.begin(),r.end());
return r;
}
int main(){
freopen("banal.in","r",stdin);
freopen("banal.out","w",stdout);
cst[2][2]=1;
cst[3][3]=1;
cst[4][2]=2;
cst[5][5]=1;
cst[6][2]=cst[6][3]=1;
cst[7][7]=1;
cst[8][2]=3;
cst[9][3]=2;
int n;
p10[0]=1;
for (int i=1;i<=18;i++){
p10[i]=p10[i-1]*10;
}
cin>>n;
cin>>s;
string a,b;
a=s.substr(0,n);b=s.substr(n);
bool a0=false,b0=false;
int cc=0,ca=0,cb=0;
for (int i=0;i<s.size();i++) if (s[i]=='?') cc++;
for (int i=0;i<n;i++) a0|=(a[i]=='0');
for (int i=0;i<n;i++) if (a[i]=='?') ca++;
cb=cc-ca;
for (int i=0;i<n;i++) b0|=(b[i]=='0');
if (a0 && b0){
printf("%s\n0\n",mul(tostr(p10[ca]),tostr(p10[cb])).c_str());
return 0;
}
if (a0 && !b0){
LL coef=p10[ca];
LL bad=0;int coo=1;
for (int j=0;j<=cb;j++){
bad+=coo*C(cb,j)*p10[cb-j];
coo=-coo;
}
LL good=p10[cb]-bad;
string r1=mul(tostr(good),tostr(coef));
string r2=mul(tostr(bad),tostr(coef));
printf("%s\n%s\n",r1.c_str(),r2.c_str());
return 0;
}
if (!a0 && b0){
LL coef=p10[cb];
LL bad=0;
int coo=1;
for (int j=0;j<=ca;j++){
bad+=coo*C(ca,j)*p10[ca-j];
coo=-coo;
}
LL good=p10[ca]-bad;
string r1=mul(tostr(good),tostr(coef));
string r2=mul(tostr(bad),tostr(coef));
printf("%s\n%s\n",r1.c_str(),r2.c_str());
return 0;
}
dp[0][0][0][0][0]=1;
for (int ii=0;ii<n;ii++){
int i=ii&1;
for (int c2=0;c2<=54;c2++){
for (int c3=0;c3<=37;c3++){
for (int c5=0;c5<=18;c5++){
for (int c7=0;c7<=18;c7++){
dp[i^1][c2][c3][c5][c7]=0;
}
}
}
}
for (int c2=0;c2<=54;c2++){
for (int c3=0;c3<=37;c3++){
for (int c5=0;c5<=19;c5++){
for (int c7=0;c7<=19;c7++){
if (dp[i][c2][c3][c5][c7]==0) continue;
if (a[ii]!='?'){
int v=a[ii]-'0';
dp[i^1][c2+cst[v][2]][c3+cst[v][3]][c5+cst[v][5]][c7+cst[v][7]]+=dp[i][c2][c3][c5][c7];
}
else{
for (int v=1;v<=9;v++){
dp[i^1][c2+cst[v][2]][c3+cst[v][3]][c5+cst[v][5]][c7+cst[v][7]]+=dp[i][c2][c3][c5][c7];
}
}
}
}
}
}
}
for (int c2=0;c2<=54;c2++){
for (int c3=0;c3<=37;c3++){
for (int c5=0;c5<=18;c5++){
for (int c7=0;c7<=18;c7++){
A[c2][c3][c5][c7]=dp[n&1][c2][c3][c5][c7];
}
}
}
}
memset(dp,0,sizeof(dp));
dp[0][0][0][0][0]=1;
for (int ii=0;ii<n;ii++){
int i=ii&1;
for (int c2=0;c2<=54;c2++){
for (int c3=0;c3<=37;c3++){
for (int c5=0;c5<=18;c5++){
for (int c7=0;c7<=18;c7++){
dp[i^1][c2][c3][c5][c7]=0;
}
}
}
}
for (int c2=0;c2<=54;c2++){
for (int c3=0;c3<=37;c3++){
for (int c5=0;c5<=19;c5++){
for (int c7=0;c7<=19;c7++){
if (dp[i][c2][c3][c5][c7]==0) continue;
if (b[ii]!='?'){
int v=b[ii]-'0';
dp[i^1][c2+cst[v][2]][c3+cst[v][3]][c5+cst[v][5]][c7+cst[v][7]]+=dp[i][c2][c3][c5][c7];
}
else{
for (int v=1;v<=9;v++){
dp[i^1][c2+cst[v][2]][c3+cst[v][3]][c5+cst[v][5]][c7+cst[v][7]]+=dp[i][c2][c3][c5][c7];
}
}
}
}
}
}
}
for (int c2=0;c2<=54;c2++){
for (int c3=0;c3<=37;c3++){
for (int c5=0;c5<=18;c5++){
for (int c7=0;c7<=18;c7++){
B[c2][c3][c5][c7]=dp[n&1][c2][c3][c5][c7];
}
}
}
}
string good="0";
for (int c2=0;c2<=54;c2++){
for (int c3=0;c3<=37;c3++){
for (int c5=0;c5<=18;c5++){
for (int c7=0;c7<=18;c7++){
LL t1=A[c2][c3][c5][c7],t2=B[c2][c3][c5][c7];
if (t1>0 && t2>0){
// cout<<c2<<c3<<c5<<c7<<endl;
// P(t1*t2);
good=add(good,mul(tostr(t1),tostr(t2)));
}
}
}
}
}
//P(good);
LL ba=0;
LL ccc=1;
for (int i=0;i<=ca;i++){
ba+=ccc*C(ca,i)*p10[ca-i];
ccc*=-1;
}
LL ga=p10[ca]-ba;
//cout<<ba<<ga<<endl;
LL bb=0;
ccc=1;
for (int i=0;i<=cb;i++){
bb+=ccc*C(cb,i)*p10[cb-i];
ccc*=-1;
}
LL gb=p10[cb]-bb;
//cout<<ba<<ga<<endl;
string rr=mul(tostr(ga),tostr(gb));
rr=add(rr,good);
//P(rr);
//P(good);
//rr+=good;
string tot=mul(tostr(p10[ca]),tostr(p10[cb]));
if (rr=="") rr="0";
printf("%s\n",rr.c_str());
string mn=minuss(tot,rr);
if (mn=="") mn="0";
printf("%s\n",mn.c_str());
return 0;
}