- 注册时间
- 2008-2-23
- 最后登录
- 1970-1-1
- 威望
- 星
- 金币
- 枚
- 贡献
- 分
- 经验
- 点
- 鲜花
- 朵
- 魅力
- 点
- 上传
- 次
- 下载
- 次
- 积分
- 507
- 在线时间
- 小时
|
发表于 2010-7-2 21:47:47
|
显示全部楼层
本帖最后由 ssikkiss 于 2010-7-2 22:05 编辑
此题网上以有人做出。
我抄写了它的c++代码,编译出错,稍更改了下,可以通过,不过请自己加入main函数-
- const int NMax = 1<<22;
- const int SomeMore = 600;
- const int PolyTempMax = 1<<11;
- #define NUMBERTYPE long
- NUMBERTYPE * Global = new NUMBERTYPE[4*NMax + SomeMore];
- long CountAdd;
- long CountMul;
- // Standard circular convolution
- void CircConv(long N, NUMBERTYPE *X, NUMBERTYPE *H, NUMBERTYPE *Y) {
- long i, j;
- for (i = 0; i < N ;i++)
- Y[i] = 0;
- for (i = 0; i < N ;i++)
- for (j = 0; j < N ;j++)
- if (i + j < N)
- Y[i + j] += X[j] * H[i];
- else
- Y[i + j - N] += X[j] * H[i];
- }
- void WriteResult(long N, NUMBERTYPE *X) {
- long i;
- long t=0;
- for (i = 0; i < N; i++) {
- t+=X[i];
- cout<<t%10;
- t/=10;
- }
- printf("\n");
- }
- void ModuloPlusMinus(long N, long X) {
- long i;
- NUMBERTYPE Temp;
- for (i = 0; i < N; i++) {
- Temp = Global[X + i];
- Global[X + i] = Temp - Global[X + i + N];
- Global[X + i + N] = Temp + Global[X + i + N];
- }
- CountAdd += N<<1;
- }
- void MulAddDiv(long N, long X1, long X2) {
- long i;
- NUMBERTYPE Temp;
- for (i = 0; i < N; i++) {
- Temp = Global[X1 + i];
- Global[X1 + i] = (Temp + Global[X2 + i])>>1;
- Global[X1 + i + N] = (-Temp + Global[X2 + i])>>1;
- }
- CountAdd += N<<1;
- }
- void PermutePolySub(long N, long K, long X, NUMBERTYPE * Y, long Z) {
- long i;
- long adr;
- long ex;
- for (i = 0; i < N; i++) {
- adr = (i + K + 2 * N * N) % N;
- ex = ((i + K + 2 * N * N) / N) & 1;
- if (ex == 0) {
- Global[Z + adr] = Global[X + i] - Y[i];
- } else {
- Global[Z + adr] = -Global[X + i] + Y[i];
- }
- }
- CountAdd +=N;
- }
-
- void PolyAdd(long N, long X, NUMBERTYPE * Y, long Z) {
- long i;
- for (i = 0; i < N; i++) {
- Global[Z + i] = Global[X + i] + Y[i];
- }
- CountAdd +=N;
- }
-
- void PolySubPermute(long N, long K, long X, NUMBERTYPE * Y, long Z) {
- long i;
- long adr;
- long ex;
-
- for (i = 0; i < N; i++) {
- adr = (i + K + 2 * N * N) % N;
- ex = ((i + K + 2 * N * N) / N) & 1;
- if (ex == 0) {
- Global[Z + adr] = Global[X + adr] - Y[i];
- } else {
- Global[Z + adr] = Global[X + adr] + Y[i];
- }
- }
- CountAdd +=N;
- }
-
- void PolyAddPermute(long N, long K, long X, NUMBERTYPE * Y, long Z) {
- long i;
- long adr;
- long ex;
-
- for (i = 0; i < N; i++) {
- adr = (i + K + 2 * N * N) % N;
- ex = ((i + K + 2 * N * N) / N) & 1;
- if (ex == 0) {
- Global[Z + adr] = Global[X + adr] + Y[i];
- } else {
- Global[Z + adr] = Global[X + adr] - Y[i];
- }
- }
- CountAdd +=N;
- }
-
- void PolyTransNB(long N, long L2, long K, long X) {
- long i;
- long M;
- long m1;
- long P;
- long p1;
- long Q;
- long q1;
- long adr;
- NUMBERTYPE *Temp = new NUMBERTYPE[PolyTempMax];;
- M = (long)floor(0.5 + log(N) / log(2));
- P = 1;
- Q = N / 2;
- for (m1 = 0; m1 < M; m1++) {
- for (p1 = 0; p1 < P; p1++)
- for (q1 = 0; q1 < Q; q1++) {
- adr = q1 + p1 * (Q<<1);
- for (i = 0; i < L2; i++)
- Temp[i] = Global[X + L2 * (adr +Q) + i];
- PermutePolySub(L2, P * q1 * K, X + L2 * adr, Temp, X + L2 * (adr + Q));
- PolyAdd(L2, X + L2 * adr, Temp, X + L2 * adr);
- }
- P <<=1;
- Q >>=1;
- }
- delete []Temp;
- }
-
- void PolyTransBN(long N, long L2, long K, long X) {
- long i;
- long M;
- long m1;
- long P;
- long p1;
- long Q;
- long q1;
- long adr;
- NUMBERTYPE *Temp = new NUMBERTYPE[PolyTempMax];;
-
- M = (long)floor(0.5 + log(N) /log(2));
- P = N / 2;
- Q = 1;
- for (m1 = 0; m1 < M; m1++) {
- for (p1 = 0; p1 < P; p1++)
- for (q1 = 0; q1 < Q; q1++) {
- adr = q1 + 2 * p1 * Q;
- for (i = 0; i < L2; i++)
- Temp[i] = Global[X + L2 * (adr+Q)+i];
- PolySubPermute(L2, P * q1 * K,X+L2*adr,Temp,X+L2*(adr+Q));
- PolyAddPermute(L2, P * q1 * K,X + L2 * adr, Temp, X + L2 * adr);
- }
- P >>=1;
- Q <<=1;
- }
- delete []Temp;
- }
-
- void NegaConvolution(long N, long X, long H, long Y) {
- long i, k;
- long N2, N3, N4;
- long L1, L2;
- NUMBERTYPE Tp0, Tp1, Tp2;
-
- if (N==2) {
- Tp0= (Global[X] + Global[X + 1]) * Global[H];
- Tp1=(Global[H] + Global[H + 1]) * Global[X + 1];
- Tp2=(Global[H] - Global[H + 1]) * Global[X];
-
- CountMul +=3;
- Global[X] = Tp0 - Tp1;
- Global[X+1] = Tp0 - Tp2;
-
- CountAdd+=5;
- } else {
- N2=N<<1;
- N3=N2+N;
- N4=N2<<1;
-
- L2 = (long)floor(0.5 + sqrt(N));
- if (L2 * L2 != N)
- L2 = (long)floor(0.5 + sqrt(N2));
- L1 = N / L2;
-
- for (k=0;k<L1;k++)
- for (i=0;i<L2;i++) {
- Global[Y+L2*k+i]=Global[X + L1 * i + k];
- Global[Y+N2+L2*k+i]=Global[H + L1 * i + k];
- Global[Y+N+L2*k+i]=0;
- Global[Y+N3+L2*k+i]=0;
- }
- PolyTransNB(2 * L1, L2, L2 / L1, Y);
- PolyTransNB(2 * L1, L2, L2 / L1, Y + N2);
- for (k = 0; k < 2 * L1; k++)
- NegaConvolution(L2, Y + L2 * k, Y + N2 + L2 * k, Y + N4);
- PolyTransBN(2 * L1, L2, -(L2 / L1), Y);
- for (k = 0; k < L1; k++) {
- for (i = 1; i < L2; i++) {
- Global[X + L1 * i + k] = (Global[Y + L2 * k + i] +
- Global[Y + N + L2 * k + (i - 1)]) / (2 * L1);
- }
- Global[X + k] = (Global[Y + L2 * k] - Global[Y + N + L2 * k + L2 - 1]) / (2 * L1);
- CountAdd+=L2+1;
- }
- }
- }
-
-
- void CircConvolution(long N, long X, long H) {
- long M;
- long N2;
- long X1, X2;
- NUMBERTYPE Tp0, Tp1, Tp2;
-
- N2 = 2 * N;
- M = N / 2;
- do {
- ModuloPlusMinus(M, X);
- ModuloPlusMinus(M, H);
- NegaConvolution(M, X, H, N2);
- X += M;
- H += M;
- M /= 2;
- } while (M != 1);
-
- Tp0=(Global[X]+Global[X+1])*Global[H];
- Tp2=(Global[H]-Global[H+1]);
- Tp1=Tp2*Global[X+1];
- Tp2=Tp2*Global[X];
-
- CountAdd +=5;
- CountMul +=3;
- Global[X] = Tp0 - Tp1;
- Global[X+1] = Tp0 - Tp2;
- M = 2;
- X1 = X - M;
- X2 = X;
- do {
- MulAddDiv(M, X1, X2);
- X2 -= M;
- M <<=1;
- X1 -= M;
- } while (M != N);
- }
-
- char* testmul(int e) {
- NUMBERTYPE* sequenceOne=new NUMBERTYPE[NMax];
- NUMBERTYPE* sequenceTwo=new NUMBERTYPE[NMax];
- NUMBERTYPE* resultFast=new NUMBERTYPE[NMax];
- NUMBERTYPE* resultSlow=new NUMBERTYPE[NMax];
-
- long N;
- long X,H;
- long i;
-
- N=2;
- N<<=e;
- for (i=0;i<N/2;i++) {
- sequenceOne[i]=9;
- sequenceTwo[i]=9;
- }
-
- for (i=N/2;i<N;i++) {
- sequenceOne[i]=0;
- sequenceTwo[i]=0;
- }
-
- cout<<N<<endl;
-
-
-
-
- X=0;
- H=N;
- Timer timer;
- timer.start();
- for (i = 0; i < N; i++) {
- Global[X + i] = sequenceOne[i];
- Global[H + i] = sequenceTwo[i];
- }
- CountAdd = 0;
- CountMul = 0;
- CircConvolution(N, X, H);
- timer.end();
- cout<<"test mul:耗时"<<timer.getSecond()<<"秒"<<endl;
- //WriteResult(N, Global); // First part of Global contains the convolution
- printf("\n");
-
-
- //CircConv(N, sequenceOne, sequenceTwo, resultSlow);
- //WriteResult(N, resultSlow);
- cout<<"Additions:"<<CountAdd<<endl;
- cout<<"Multiplications:"<<CountMul<<endl;
-
- char* ret=(char*)malloc(sizeof(char)*(N+2));
-
- long t=0;
- for (i = 0; i < N; i++) {
- t+=Global[i];
- ret[i]=t%10+'0';
- t/=10;
- }
- ret[i++]=0;
-
- return ret;
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
复制代码 |
|