BZOJ 1498: [NOI2006]神奇的口袋 性质分析+高精度
我们发现我们可以直接让 $x_{i}=i$,然后模拟就行了.
code:
#include <cstdio> #include <cstring> #include <cmath> #include <vector> #include <map> #include <algorithm> #define N 500005 #define ll long long #define setIO(s) freopen(s".in","r",stdin) ,freopen(s".out","w",stdout) using namespace std; const double pi=acos(-1); char S[N]; struct cp { double x,y; cp(double a=0,double b=0) { x=a,y=b; } cp operator+(const cp b) { return cp(x+b.x,y+b.y); } cp operator-(const cp b) { return cp(x-b.x,y-b.y); } cp operator*(const cp b) { return cp(x*b.x-y*b.y,x*b.y+y*b.x); } }A[N],B[N]; int mem[N*10],*ptr=mem; void FFT(cp *a,int len,int flag) { int i,j,k,mid; for(i=k=0;i<len;++i) { if(i>k) swap(a[i],a[k]); for(j=len>>1;(k^=j)<j;j>>=1); } for(mid=1;mid<len;mid<<=1) { cp wn(cos(pi/mid), flag*sin(pi/mid)),x,y; for(i=0;i<len;i+=mid<<1) { cp w(1,0); for(j=0;j<mid;++j) { x=a[i+j],y=w*a[i+j+mid]; a[i+j]=x+y,a[i+j+mid]=x-y; w=w*wn; } } } if(flag==-1) { for(i=0;i<len;++i) a[i].x/=(double)len; } } struct num { int len; int *a; num(){} num(int l) { len=l,a=ptr,ptr+=l; } void fix(int l) { len=l,a=ptr,ptr+=l; } void get_mod(int l) { len=l; } num operator*(const num &b) { num c(len+b.len+1); int lim=1,i,j,l=b.len; while(lim<=c.len) lim<<=1; for(i=0;i<lim;++i) { A[i].x=A[i].y=0; B[i].x=B[i].y=0; } for(i=0;i<len;++i) A[i].x=a[i]; for(i=0;i<b.len;++i) B[i].x=b.a[i]; FFT(A,lim,1),FFT(B,lim,1); for(i=0;i<lim;++i) A[i]=A[i]*B[i]; FFT(A,lim,-1); for(i=0;i<c.len;++i) c.a[i]=(int)(A[i].x+0.5); for(i=0;i<c.len-1;++i) { c.a[i+1]+=c.a[i]/10; c.a[i]%=10; } for(i=c.len-1;i>=0;--i) if(c.a[i]) break; c.get_mod(i+1); return c; } num operator+(const num &b) { num c(max(len,b.len)+1); int i,j; for(i=0;i<b.len;++i) c.a[i]=b.a[i]; for(i=0;i<len;++i) c.a[i]+=a[i]; for(i=0;i<c.len-1;++i) { c.a[i+1]+=c.a[i]/10; c.a[i]%=10; } for(i=c.len-1;i>=0;--i) if(c.a[i]) break; c.get_mod(i+1); return c; } num operator-(const num &b) { num c(len); int i,j; for(i=0;i<len;++i) c.a[i]=a[i]; for(i=0;i<b.len;++i) c.a[i]-=b.a[i]; for(i=0;i<c.len-1;++i) { if(c.a[i]<0) { c.a[i+1]-=(-c.a[i])/10+((-c.a[i])%10!=0); c.a[i]=(c.a[i]%10+10)%10; } } for(i=c.len-1;i>=0;--i) if(c.a[i]) break; c.get_mod(i+1); return c; } num operator/(const int b) { num c(len); int i,j,re=0; for(i=len-1;i>=0;--i) { re=re*10+a[i]; c.a[i]=re/b; re%=b; } for(i=c.len-1;i>=0;--i) { if(c.a[i]) break; } c.get_mod(i+1); return c; } void print() { for(int i=len-1;i>=0;--i) printf("%d",a[i]); } void input() { scanf("%s",S); int l=strlen(S); fix(l); for(int i=0;i<l;++i) a[i]=S[l-1-i]-'0'; } void modify(int x) { int base=1,i,j; for(i=0;base<=x;++i,base*=10); fix(i); for(j=0;j<i;++j) a[j]=x%10,x/=10; } }; int a[N],mul[N],dn[N]; void calc(int x,int *arr) { int i,j; for(i=2;i<=x;++i) { if(x%i==0) { while(x%i==0) x/=i,arr[i]++; } } if(x) arr[x]++; } int main() { // setIO("input"); int i,j,t,n,d,sum=0; scanf("%d%d%d",&t,&n,&d); for(i=1;i<=t;++i) scanf("%d",&a[i]),sum+=a[i]; for(i=1;i<=n;++i) { int x,y; scanf("%d%d",&x,&y); if(!a[y]) { printf("0/1\n"); return 0; } calc(a[y],mul); calc(sum,dn); sum+=d; a[y]+=d; } for(i=2;i<N;++i) { int tmp=min(mul[i],dn[i]); mul[i]-=tmp; dn[i]-=tmp; } num ans,det; ans.modify(1); for(i=2;i<N;++i) { det.modify(i); for(j=1;j<=mul[i];++j) ans=ans*det; } ans.print(); printf("/"); ans.modify(1); for(i=2;i<N;++i) { if(!dn[i]) continue; det.modify(i); for(j=1;j<=dn[i];++j) ans=ans*det; } ans.print(); return 0; }