傳送門ios
題目大意git
有2*n個位置,這些位置有的已經填上了數,有的尚未(用?表示),如今讓你在尚未填上數的填0~9中的任意數,使得前n個數的乘積等於後n個數的乘積,問有多少種方案。數組
分析優化
首先這個題 並無取模,因此咱們要使用高精度。在這個題中我爲了加速,將樸素的高精度變成了5個long long類型。而後咱們將問題分爲先考慮填1~9,再單獨考慮填0的狀況這兩個子問題。ui
1.考慮填1~9spa
咱們首先會想到的天然是dpij表示考慮到第i個數,乘積爲j的方案數。但咱們們發現因爲乘積可能會很大,因此這樣是不可行的。因而咱們考慮優化,不難發現咱們能夠將全部1~9之中的數寫爲2p13p25p37p4的形式,因而推而廣之,對於全部這些有1~9的數構成的數均可以寫爲這個形式。可是因爲空間極小,這樣仍是不行的,然而對於全部i都只與i-1有關,因此咱們可使用滾動數組。而後咱們再通過精妙的計算能夠發現對於每一個dp數組的答案都不會超過long long的範圍,因此咱們只須要用long long記錄,到統計答案時在轉化爲高精度形式就好了。對於這一部分的答案就是對於每一個不一樣的四元組(p1,p2,p3,p4)所對應的前半段的dp值乘後半段的dp值。code
2.考慮填0blog
對於每一段,咱們能夠枚舉填1~n個0,而這一段的方案數∑C(n,i)9^(n-i),而最終答案即是前半段求出的值乘上後半段乘上的值。ci
注意get
有可能前半段或者後半段已經填過0了,那咱們就要特判這種狀況呢,這種狀況的計算和考慮填0這一部分的思想類似,只不過能夠不填0(即i能夠等於0)。
具體實現見代碼
代碼
#include<iostream> #include<cstdio> #include<cstring> #include<string> #include<algorithm> #include<cctype> #include<cmath> #include<cstdlib> #include<queue> #include<ctime> #include<vector> #include<set> #include<map> #include<stack> #include<unordered_map>
using namespace std; #define ct cout
#define el endl
#define fi first
#define se second
#define pf printf
#define li long long
#define pb push_back
#define mkp make_pair
#define vi vector<int>
#define y1 y12345678909
#define rii register int
#define pii pair<int,int>
#define ck(x) cout<<x<<endl;
#define ui unsigned int
#define clr(x) memset(x,0,sizeof(x))
#define sp cout<<"---------------------------------------------------"<<endl
const li Tot=1e9; inline int ra(){ int _x=0,_f=1;char _s=getchar(); while(!isdigit(_s)){if(_s=='-')_f=-1;_s=getchar();} while(isdigit(_s)){_x=(_x<<3)+(_x<<1)+(_s-'0');_s=getchar();} return _x*_f; } struct mint { li _[6]; int __; }; mint operator + (mint _x,mint _y){ int _k; li _g=0; mint _z; for(rii _i=_x.__+1;_i<=5;++_i)_x._[_i]=0; for(rii _i=_y.__+1;_i<=5;++_i)_y._[_i]=0; if(_x.__>_y.__)_k=_x.__; else _k=_y.__; for(rii _i=1;_i<=_k;++_i){ _z._[_i]=(_x._[_i]+_y._[_i]+_g)%Tot; _g=(_x._[_i]+_y._[_i]+_g)/Tot; } if(_g>0){ _z._[++_k]=_g; } _z.__=_k; return _z; } mint operator - (mint _x,mint _y){ int _k; _k=_x.__; for(rii _i=_x.__+1;_i<=5;++_i)_x._[_i]=0; for(rii _i=_y.__+1;_i<=5;++_i)_y._[_i]=0; for(rii _i=1;_i<=_k;++_i){ if(_x._[_i]<_y._[_i]){ _x._[_i]+=Tot; _x._[_i+1]--; } _x._[_i]-=_y._[_i]; } while(_k>1&&_x._[_k]==0)_k--; _x.__=_k; return _x; } mint operator * (mint _x,mint _y){ int _k; li _g=0; mint _z; for(rii _i=_x.__+1;_i<=5;++_i)_x._[_i]=0; for(rii _i=_y.__+1;_i<=5;++_i)_y._[_i]=0; _k=_x.__+_y.__-1; for(rii _i=0;_i<=5;++_i) _z._[_i]=0; for(rii _i=1;_i<=_x.__;++_i) for(rii _j=1;_j<=_y.__;++_j) _z._[_i+_j-1]+=_x._[_i]*_y._[_j]; for(rii _i=1;_i<=_k;++_i){ li _a=_z._[_i]+_g; _z._[_i]=_a%Tot; _g=_a/Tot; } while(_g){ _z._[++_k]=_g%Tot; _g/=Tot; } while(_k>1&&_z._[_k]==0)_k--; _z.__=_k; return _z; } void pr(mint _x){ for(rii _i=_x.__;_i>0;--_i) if(_i!=_x.__&&_x._[_i]==0){ for(rii _j=1;_j<=9;++_j)cout<<0; }else if(_i!=_x.__){ li _m=_x._[_i]; int _k=0; while(_m){ _m/=10; _k++; } for(rii _j=1;_j<=9-_k;++_j)cout<<0; cout<<_x._[_i]; } else cout<<_x._[_i]; puts(""); } //---------------------------------------------------------------------------//
//---------------------------------------------------------------------------// li dp[2][2][59][40][21][21]; int a[2][19],tot[2],P[19][5],za,zb,now[3]; mint g[19],c[19][19]; inline void init(){ for(rii i=1;i<=9;++i){ int m=i; while(m%2==0){ P[i][1]++; m/=2; } while(m%3==0){ P[i][2]++; m/=3; } while(m%5==0){ P[i][3]++; m/=5; } while(m%7==0){ P[i][4]++; m/=7; } } return; } inline void Get(){ for(rii i=0;i<=18;++i) for(rii j=0;j<=18;++j) c[i][j]._[1]=0,c[i][j].__=1; c[0][0].__=1; c[0][0]._[1]=1; for(rii i=1;i<=18;++i) c[i][0].__=c[i][0]._[1]=c[i][i].__=c[i][i]._[1]=1; for(rii i=1;i<=18;++i) for(rii j=1;j<i;++j) c[i][j]=c[i-1][j]+c[i-1][j-1]; g[0].__=g[0]._[1]=1; mint nin; nin.__=1,nin._[1]=9; for(rii i=1;i<=18;++i)g[i]=g[i-1]*nin; } inline mint pw(mint a,int p){ mint res; res.__=res._[1]=1; while(p){ if(p&1)res=res*a; a=a*a; p>>=1; } return res; } inline void deal(){ mint Ans; Ans.__=1,Ans._[1]=0; if(za&&!zb){ for(rii i=0;i<=tot[0];++i) for(rii j=0;j<tot[1];++j) Ans=Ans+(g[i]*c[tot[0]][tot[0]-i]*g[j]*c[tot[1]][tot[1]-j]); }else if(!za&&zb){ for(rii i=0;i<tot[0];++i) for(rii j=0;j<=tot[1];++j) Ans=Ans+(g[i]*c[tot[0]][tot[0]-i]*g[j]*c[tot[1]][tot[1]-j]); }else { for(rii i=0;i<=tot[0];++i) for(rii j=0;j<=tot[1];++j) Ans=Ans+(g[i]*c[tot[0]][tot[0]-i]*g[j]*c[tot[1]][tot[1]-j]); } pr(Ans); mint ten; ten.__=1; ten._[1]=10; pr(pw(ten,tot[0]+tot[1])-Ans); exit(0); } mint xx,yy; inline mint gt(li wh){ mint res; res.__=0; while(wh){ res._[++res.__]=wh%Tot; wh/=Tot; } return res; } mint ch(li A,li B){ xx=gt(A),yy=gt(B); return xx*yy; } int main(){ freopen("banal.in","r",stdin); freopen("banal.out","w",stdout); memset(P,0,sizeof(P)); int n,m; now[0]=now[1]=0; tot[0]=tot[1]=0; za=zb=0; char s; init(); Get(); n=ra(); for(rii i=1;i<=n;++i){ cin>>s; if(s=='?')a[0][i]=-1,tot[0]++; else a[0][i]=s-'0'; if(s=='0')za++; } for(rii i=1;i<=n;++i){ cin>>s; if(s=='?')a[1][i]=-1,tot[1]++; else a[1][i]=s-'0'; if(s=='0')zb++; } if(za>0||zb>0){ deal(); return 0; } clr(dp[0][0]);clr(dp[1][0]); dp[0][0][0][0][0][0]=dp[1][0][0][0][0][0]=1; for(int _=0;_<=1;_++) for(rii i=1;i<=n;++i){ now[_]^=1; clr(dp[_][now[_]]); if(a[_][i]!=-1){ for(rii p1=0;p1<=i*3;++p1) for(rii p2=0;p2<=i*2;++p2) for(rii p3=0;p3<=i;++p3) for(rii p4=0;p4<=i;++p4){ int P1=p1+P[a[_][i]][1],P2=p2+P[a[_][i]][2], P3=p3+P[a[_][i]][3],P4=p4+P[a[_][i]][4]; dp[_][now[_]][P1][P2][P3][P4]= dp[_][now[_]][P1][P2][P3][P4]+ dp[_][now[_]^1][p1][p2][p3][p4]; } }else { for(rii p1=0;p1<=i*3;++p1) for(rii p2=0;p2<=i*2;++p2) for(rii p3=0;p3<=i;++p3) for(rii p4=0;p4<=i;++p4) for(rii j=1;j<=9;++j){ int P1=p1+P[j][1],P2=p2+P[j][2],P3=p3+P[j][3],P4=p4+P[j][4]; dp[_][now[_]][P1][P2][P3][P4]= dp[_][now[_]][P1][P2][P3][P4]+ dp[_][now[_]^1][p1][p2][p3][p4]; } } } mint Ans; Ans.__=1,Ans._[1]=0; for(rii p1=0;p1<=n*3;++p1) for(rii p2=0;p2<=n*2;++p2) for(rii p3=0;p3<=n;++p3) for(rii p4=0;p4<=n;++p4){ Ans=Ans+ch(dp[0][now[0]][p1][p2][p3][p4],dp[1][now[1]][p1][p2][p3][p4]); } for(rii i=0;i<tot[0];++i) for(rii j=0;j<tot[1];++j) Ans=Ans+(g[i]*c[tot[0]][tot[0]-i]*g[j]*c[tot[1]][tot[1]-j]); pr(Ans); mint ten; ten.__=1; ten._[1]=10; pr(pw(ten,tot[0]+tot[1])-Ans); return 0; }