题意:
给出一个长度为n的数列p,数列中数字两两互质;
有一个无限长的寄存器,现从p[1]开始,依次将其所有的倍数在寄存器中置为p[i];
求最后每个数字所染色区域在寄存器中占比,用一个既约分数表示;
n<=1000,p[i]<=maxint;
题解:
这傻逼题我居然傻逼了一晚上;
说白了就是一个递推,f[i]=1/p[i] *Π(p[j]-1)/p[j];
这坨东西多好推啊,要是这题输出浮点数多好;
然并卵,显然这东西乘个n次早就爆long long了;
于是要上高精度;
上高精度可不容易,这就要考虑考虑这个式子怎么求方便了;
显然Π(p[i]-1)/p[i]可以通过后缀积来搞搞,由最后面推过来;
每次只要分子分母同乘低精度就好;
而最后的f[i]也就是分母乘个p[i]的事;
然而并不能直接输出,因为题中要的是既约分数。。。
高精GCD+高精除高精?
开玩笑吧!我还能有那码力?
首先一个显然的事,如果a与c互质,b与c互质,那么a*b与c互质;
然后我们只需要将每次低精乘高精之前,对另一个高精求一下GCD;
然后低精与另一个高精除掉这个GCD,就依然保持分数为既约形式;
这样只需要低精与高精的GCD,和高精除低精了;
高精除低精不用说,况且还是保证整除;
GCD这我就逗了,被坑的去写了一个除二讨论的GCD;
这特么。。我居然以为高精度的log很小。。。
总复杂度O(n^2log(高精度))=O(n^3)四舍五入就是一个亿啊!
真是被逗的不轻,然后我就写了个√n的质因数分解。。
只要每次分出的质因数去判断高精度能不能除掉就好了;
直接加起来边模边算,反正都是同余系下;
然后这题就结束了,复杂度O(n^2√n);
代码:
#include<stdio.h> #include<string.h> #include<algorithm> #define N 2100 #define M 1100 #define mod 10000 using namespace std; typedef long long ll; struct BIG { int a[N],top; void print() { int i=top; printf("%d",a[i--]); while(i>=0) printf("%04d",a[i--]); } bool judge(int p) { int ret=0; for(int i=top;i>=0;i--) { ret=(ret*mod%p+a[i])%p; } return !ret; } friend bool operator ==(BIG &a,BIG &b) { memcpy(a.a,b.a,sizeof(int)*(b.top+1)); a.top=b.top; } friend bool operator <(BIG &a,int b) { if(a.top>=3) return 0; if(a.top==2) return (ll)a.a[2]*mod*mod+a.a[1]*mod+a.a[0]<b; if(a.top==1) return a.a[1]*mod+a.a[0]<b; if(a.top==0) return a.a[0]<b; } friend void operator -=(BIG &a,int b) { a.a[2]-=b/mod/mod; a.a[1]-=b/mod%mod; a.a[0]-=b%mod; while(a.a[a.top]==0&&a.top) a.top--; } friend void operator *=(BIG &b,int a) { static int i; ll index,up; for(i=0,up=0;i<=b.top;i++) { index=up+(ll)a*b.a[i]; b.a[i]=index%mod; up=index/mod; } while(up) b.a[++b.top]=up%mod, up=up/mod; } friend void operator /=(BIG &a,int b) { static int i,up; static ll index; i=a.top,up=0; while(i>=0) { index=(ll)up*mod+a.a[i]; a.a[i]=index/b; up=index%b; i--; } while(a.a[a.top]==0&&a.top) a.top--; } friend int gcd(int a,BIG &b) { static BIG temp; memcpy(temp.a,b.a,sizeof(int)*(b.top+1)); temp.top=b.top; int ret=1; for(int i=2;i*i<=a;i++) { if(a%i==0) { while(a%i==0&&temp.judge(i)) { a/=i; temp/=i; ret*=i; } while(a%i==0) a/=i; } } if(a!=1) if(temp.judge(a)) ret*=a; return ret; } }up[1100],down[1100]; int p[1100]; int main() { int n,m,i,j,k; scanf("%d",&n); for(i=1;i<=n;i++) scanf("%d",p+i); up[n+1].a[0]=down[n+1].a[0]=1; for(i=n;i>1;i--) { up[i]==up[i+1]; down[i]==down[i+1]; if(p[i]-1==0) { memset(up[i].a,0,sizeof(int)*(up[i].top+1)); memset(down[i].a,0,sizeof(int)*(down[i].top+1)); up[i].top=0; down[i].top=0; down[i].a[0]=1; } else { k=gcd(p[i]-1,down[i+1]); down[i]/=k; up[i]*=(p[i]-1)/k; } k=gcd(p[i],up[i]); up[i]/=k; down[i]*=p[i]/k; } for(i=2;i<=n+1;i++) { k=gcd(p[i-1],up[i]); up[i]/=k; down[i]*=p[i-1]/k; } for(i=2;i<=n+1;i++) { up[i].print(); putchar('/'); down[i].print(); putchar('\n'); } return 0; }
原文地址:http://blog.csdn.net/ww140142/article/details/48462139