100725B Banal Tickets
题目大意
有2*n个位置,这些位置有的已经填上了数,有的还没有(用?表示),现在让你在还没有填上数的填0~9中的任意数,使得前n个数的乘积等于后n个数的乘积,问有多少种方案。
分析
首先这个题 并没有取模,所以我们要使用高精度。在这个题中我为了加速,将朴素的高精度变成了5个long long类型。然后我们将问题分为先考虑填1~9,再单独考虑填0的情况这两个子问题。
1.考虑填1~9
我们首先会想到的自然是dpij表示考虑到第i个数,乘积为j的方案数。但我们们发现由于乘积可能会很大,所以这样是不可行的。于是我们考虑优化,不难发现我们可以将所有1~9之中的数写为2p13p25p37p4的形式,于是推而广之,对于所有这些有1~9的数构成的数都可以写为这个形式。但是由于空间极小,这样还是不行的,然而对于所有i都只与i-1有关,所以我们可以使用滚动数组。然后我们再经过精妙的计算可以发现对于每个dp数组的答案都不会超过long long的范围,所以我们只需要用long long记录,到统计答案时在转化为高精度形式就行了。对于这一部分的答案就是对于每个不同的四元组(p1,p2,p3,p4)所对应的前半段的dp值乘后半段的dp值。
2.考虑填0
对于每一段,我们可以枚举填1~n个0,而这一段的方案数∑C(n,i)9^(n-i),而最终答案便是前半段求出的值乘上后半段乘上的值。
注意
有可能前半段或者后半段已经填过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=,_f=;char _s=getchar();
while(!isdigit(_s)){if(_s=='-')_f=-;_s=getchar();}
while(isdigit(_s)){_x=(_x<<)+(_x<<)+(_s-'');_s=getchar();}
return _x*_f;
}
struct mint {
li _[];
int __;
};
mint operator + (mint _x,mint _y){
int _k;
li _g=;
mint _z;
for(rii _i=_x.__+;_i<=;++_i)_x._[_i]=;
for(rii _i=_y.__+;_i<=;++_i)_y._[_i]=;
if(_x.__>_y.__)_k=_x.__;
else _k=_y.__;
for(rii _i=;_i<=_k;++_i){
_z._[_i]=(_x._[_i]+_y._[_i]+_g)%Tot;
_g=(_x._[_i]+_y._[_i]+_g)/Tot;
}
if(_g>){
_z._[++_k]=_g;
}
_z.__=_k;
return _z;
}
mint operator - (mint _x,mint _y){
int _k;
_k=_x.__;
for(rii _i=_x.__+;_i<=;++_i)_x._[_i]=;
for(rii _i=_y.__+;_i<=;++_i)_y._[_i]=;
for(rii _i=;_i<=_k;++_i){
if(_x._[_i]<_y._[_i]){
_x._[_i]+=Tot;
_x._[_i+]--;
}
_x._[_i]-=_y._[_i];
}
while(_k>&&_x._[_k]==)_k--;
_x.__=_k;
return _x;
}
mint operator * (mint _x,mint _y){
int _k;
li _g=;
mint _z;
for(rii _i=_x.__+;_i<=;++_i)_x._[_i]=;
for(rii _i=_y.__+;_i<=;++_i)_y._[_i]=;
_k=_x.__+_y.__-;
for(rii _i=;_i<=;++_i)
_z._[_i]=;
for(rii _i=;_i<=_x.__;++_i)
for(rii _j=;_j<=_y.__;++_j)
_z._[_i+_j-]+=_x._[_i]*_y._[_j];
for(rii _i=;_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>&&_z._[_k]==)_k--;
_z.__=_k;
return _z;
}
void pr(mint _x){
for(rii _i=_x.__;_i>;--_i)
if(_i!=_x.__&&_x._[_i]==){
for(rii _j=;_j<=;++_j)cout<<;
}else if(_i!=_x.__){
li _m=_x._[_i];
int _k=;
while(_m){
_m/=;
_k++;
}
for(rii _j=;_j<=-_k;++_j)cout<<;
cout<<_x._[_i];
}
else cout<<_x._[_i];
puts("");
} //---------------------------------------------------------------------------//
//---------------------------------------------------------------------------// li dp[][][][][][];
int a[][],tot[],P[][],za,zb,now[];
mint g[],c[][];
inline void init(){
for(rii i=;i<=;++i){
int m=i;
while(m%==){
P[i][]++;
m/=;
}
while(m%==){
P[i][]++;
m/=;
}
while(m%==){
P[i][]++;
m/=;
}
while(m%==){
P[i][]++;
m/=;
}
}
return;
}
inline void Get(){
for(rii i=;i<=;++i)
for(rii j=;j<=;++j)
c[i][j]._[]=,c[i][j].__=;
c[][].__=;
c[][]._[]=;
for(rii i=;i<=;++i)
c[i][].__=c[i][]._[]=c[i][i].__=c[i][i]._[]=;
for(rii i=;i<=;++i)
for(rii j=;j<i;++j)
c[i][j]=c[i-][j]+c[i-][j-];
g[].__=g[]._[]=;
mint nin;
nin.__=,nin._[]=;
for(rii i=;i<=;++i)g[i]=g[i-]*nin;
}
inline mint pw(mint a,int p){
mint res;
res.__=res._[]=;
while(p){
if(p&)res=res*a;
a=a*a;
p>>=;
}
return res;
}
inline void deal(){
mint Ans;
Ans.__=,Ans._[]=;
if(za&&!zb){
for(rii i=;i<=tot[];++i)
for(rii j=;j<tot[];++j)
Ans=Ans+(g[i]*c[tot[]][tot[]-i]*g[j]*c[tot[]][tot[]-j]);
}else if(!za&&zb){
for(rii i=;i<tot[];++i)
for(rii j=;j<=tot[];++j)
Ans=Ans+(g[i]*c[tot[]][tot[]-i]*g[j]*c[tot[]][tot[]-j]);
}else {
for(rii i=;i<=tot[];++i)
for(rii j=;j<=tot[];++j)
Ans=Ans+(g[i]*c[tot[]][tot[]-i]*g[j]*c[tot[]][tot[]-j]);
}
pr(Ans);
mint ten;
ten.__=;
ten._[]=;
pr(pw(ten,tot[]+tot[])-Ans);
exit();
}
mint xx,yy;
inline mint gt(li wh){
mint res;
res.__=;
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,,sizeof(P));
int n,m;
now[]=now[]=;
tot[]=tot[]=;
za=zb=;
char s;
init();
Get();
n=ra();
for(rii i=;i<=n;++i){
cin>>s;
if(s=='?')a[][i]=-,tot[]++;
else a[][i]=s-'';
if(s=='')za++;
}
for(rii i=;i<=n;++i){
cin>>s;
if(s=='?')a[][i]=-,tot[]++;
else a[][i]=s-'';
if(s=='')zb++;
}
if(za>||zb>){
deal();
return ;
}
clr(dp[][]);clr(dp[][]);
dp[][][][][][]=dp[][][][][][]=;
for(int _=;_<=;_++)
for(rii i=;i<=n;++i){
now[_]^=;
clr(dp[_][now[_]]);
if(a[_][i]!=-){
for(rii p1=;p1<=i*;++p1)
for(rii p2=;p2<=i*;++p2)
for(rii p3=;p3<=i;++p3)
for(rii p4=;p4<=i;++p4){
int P1=p1+P[a[_][i]][],P2=p2+P[a[_][i]][],
P3=p3+P[a[_][i]][],P4=p4+P[a[_][i]][];
dp[_][now[_]][P1][P2][P3][P4]=
dp[_][now[_]][P1][P2][P3][P4]+
dp[_][now[_]^][p1][p2][p3][p4];
}
}else {
for(rii p1=;p1<=i*;++p1)
for(rii p2=;p2<=i*;++p2)
for(rii p3=;p3<=i;++p3)
for(rii p4=;p4<=i;++p4)
for(rii j=;j<=;++j){
int P1=p1+P[j][],P2=p2+P[j][],P3=p3+P[j][],P4=p4+P[j][];
dp[_][now[_]][P1][P2][P3][P4]=
dp[_][now[_]][P1][P2][P3][P4]+
dp[_][now[_]^][p1][p2][p3][p4];
}
}
}
mint Ans;
Ans.__=,Ans._[]=;
for(rii p1=;p1<=n*;++p1)
for(rii p2=;p2<=n*;++p2)
for(rii p3=;p3<=n;++p3)
for(rii p4=;p4<=n;++p4){
Ans=Ans+ch(dp[][now[]][p1][p2][p3][p4],dp[][now[]][p1][p2][p3][p4]);
}
for(rii i=;i<tot[];++i)
for(rii j=;j<tot[];++j)
Ans=Ans+(g[i]*c[tot[]][tot[]-i]*g[j]*c[tot[]][tot[]-j]);
pr(Ans);
mint ten;
ten.__=;
ten._[]=;
pr(pw(ten,tot[]+tot[])-Ans);
return ;
}
100725B Banal Tickets的更多相关文章
- POJ2828 Buy Tickets[树状数组第k小值 倒序]
Buy Tickets Time Limit: 4000MS Memory Limit: 65536K Total Submissions: 19012 Accepted: 9442 Desc ...
- ACM: FZU 2112 Tickets - 欧拉回路 - 并查集
FZU 2112 Tickets Time Limit:3000MS Memory Limit:32768KB 64bit IO Format:%I64d & %I64u P ...
- Tickets——H
H. Tickets Jesus, what a great movie! Thousands of people are rushing to the cinema. However, this i ...
- POJ 2828 Buy Tickets(线段树 树状数组/单点更新)
题目链接: 传送门 Buy Tickets Time Limit: 4000MS Memory Limit: 65536K Description Railway tickets were d ...
- 【poj2828】Buy Tickets
Description Railway tickets were difficult to buy around the Lunar New Year in China, so we must get ...
- [poj2828] Buy Tickets (线段树)
线段树 Description Railway tickets were difficult to buy around the Lunar New Year in China, so we must ...
- POJ 2828 Buy Tickets
Description Railway tickets were difficult to buy around the Lunar New Year in China, so we must get ...
- Buy Tickets(线段树)
Buy Tickets Time Limit:4000MS Memory Limit:65536KB 64bit IO Format:%I64d & %I64u Submit ...
- 【poj2828】Buy Tickets 线段树 插队问题
[poj2828]Buy Tickets Description Railway tickets were difficult to buy around the Lunar New Year in ...
随机推荐
- JDK自动安装脚本
A:本脚本运行的机器,Linux B:待安装JDK的机器, Linux 首先在脚本运行的机器A上确定可以ssh无密码登录到待安装jdk的机器B上,然后就可以在A上运行本脚本: 代码如下: $ ./in ...
- [SP16580]QTREE7
luogu vjudge 题意 一棵树,每个点初始有个点权和颜色(输入会给你) 0 u :询问所有u,v路径上的最大点权,要满足u,v路径上所有点的颜色都相同 1 u :反转u的颜色 2 u w :把 ...
- k2 4.6.9安装记录-够复杂了
首先需要准备一台Windows server 2008R2 系统.可以从微软官方下载. 下载地址: http://www.microsoft.com/zh-cn/download/confirmati ...
- xj监控端口,模拟登陆脚本
#!/bin/bash date=`date +%Y%m%d-%H%M` count=0 ip1=124.117.246.195 ip2=124.117.246.194 port1=(443 80 6 ...
- extjs控制器调用其他视图的函数实现控件赋值。
- Contiki学习笔记
http://blog.chinaunix.net/uid-9112803-id-2975824.html
- Web项目安全相关博客日志大集合(仅供学习及参考)
强制使用HTTPS --- Tomcat篇 ---通过在tomcat/conf/web.xml中进行配置,从而将http自动转为https.(即强制HSTS)http://blog.csdn.net/ ...
- c语言-单链表(二)
继续复习链表知识点,本章包含单链表的增加,删除,判断是否为空,和链表长度,以及链表的排序 几个知识点 1.链表的判断是否为空 //1.判断链表是否为空 bool isempty_list(PNODE ...
- Hibernate面试总结
SSH原理总结 Hibernate工作原理及为什么要用: 原理: hibernate,通过对jdbc进行封装,对 java类和 关系数据库进行mapping,实现了对关系数据库的面向对象方式的操作,改 ...
- sql语句优化方案
1. 为查询缓存优化你的查询 NOW() 和 RAND() 或是其它的诸如此类的SQL函数都不会开启查询缓存,因为这些函数的返回是会不定的易变的. 所以,你所需要的就是用一个变量来代替MySQL的函数 ...