http://msbop.openjudge.cn/bop2013/R1a_B/
比较基础的卷积题目,从卷积的定义来看,例如f(x1)和g(x2)的卷积,就是把g(x2)以y轴翻转然后在左移x3个单位,然后俩个函数相乘再在定义域上积分(离散的是求和),x3就是卷积得到函数的自变量,离散的卷积就相当于多项式的乘法。顺便存一下模板。
#include <iostream> #include <cstdio> #include <cstdlib> #include <cmath> #include <queue> #include <algorithm> #include <vector> #include <cstring> #include <stack> #include <cctype> #include <utility> #include <map> #include <string> #include <climits> #include <set> #include <string> #include <sstream> #include <utility> #include <ctime> #include <bitset> using std::priority_queue; using std::vector; using std::swap; using std::stack; using std::sort; using std::max; using std::min; using std::pair; using std::map; using std::string; using std::cin; using std::cout; using std::set; using std::queue; using std::string; using std::stringstream; using std::make_pair; using std::getline; using std::greater; using std::endl; using std::multimap; using std::deque; using std::unique; using std::lower_bound; using std::random_shuffle; using std::bitset; using std::upper_bound; typedef long long LL; typedef unsigned long long ULL; typedef pair<int, int> PAIR; typedef multimap<int, int> MMAP; typedef LL TY; typedef long double LF; const int MAXN(140010); const int MAXM(100010); const int MAXE(100010); const int MAXK(6); const int HSIZE(131313); const int SIGMA_SIZE(26); const int MAXH(19); const int INFI((INT_MAX-1) >> 1); const ULL BASE(31); const LL LIM(10000000); const int INV(-10000); const LL MOD(1000000007); const double EPS(1e-7); const LF PI(acos(-1.0)); template<typename T> void checkmax(T &a, T b){if(b > a) a = b;} template<typename T> void checkmin(T &a, T b){if(b < a) a = b;} template<typename T> T ABS(const T &a){return a < 0? -a: a;} struct COMPLEX { double a, b; COMPLEX(double a_, double b_): a(a_), b(b_){} COMPLEX(){} friend COMPLEX operator +(const COMPLEX &op1, const COMPLEX &op2){ return COMPLEX(op1.a+op2.a, op1.b+op2.b);} friend COMPLEX operator -(const COMPLEX &op1, const COMPLEX &op2){ return COMPLEX(op1.a-op2.a, op1.b-op2.b);} friend COMPLEX operator *(const COMPLEX &op1, const COMPLEX &op2){ return COMPLEX(op1.a*op2.a-op1.b*op2.b, op1.a*op2.b+op1.b*op2.a);} }; void change(COMPLEX *y, int len) { for(int i = 1, j = len/2; i < len-1; ++i) { if(i < j) swap(y[i], y[j]); int k = len/2; while(j >= k) { j -= k; k /= 2; } if(j < k) j += k; } } double rc[20], rs[20]; double COS(int h){return h < 0? rc[-h]: rc[h];} //预处理出cos和sin值 double SIN(int h){return h < 0? -rs[-h]: rs[h];} void FFT(COMPLEX *y, int len, int flag) { change(y, len); for(int h = 2, t = 1; h <= len; h <<= 1, ++t) { COMPLEX wn(COS(flag*t), SIN(flag*t)); for(int j = 0; j < len; j += h) { COMPLEX w(1, 0); int temp = h >> 1; for(int k = j; k < j+temp; ++k) { COMPLEX u = y[k]; COMPLEX t = w*y[k+temp]; y[k] = u+t; y[k+temp] = u-t; w = w*wn; } } } if(flag == -1) for(int i = 0; i < len; ++i) y[i].a /= len; } COMPLEX arr[2][10][MAXN]; char str1[50010], str2[50010]; int rec[50010]; int main() { for(int i = 1; i <= 17; ++i) { rc[i] = cos(PI*2/(1 << i)); rs[i] = sin(PI*2/(1 << i)); } int TC, n_case(0); scanf("%d", &TC); while(TC--) { scanf("%s%s", str2, str1); int len1 = strlen(str1), len2 = strlen(str2); int l = 0, r = len2-1; while(l < r) swap(str2[l++], str2[r--]); int temp = len2*2; l = 1; while(l < temp) l <<= 1; for(int i = 0; i < l; ++i) for(int j = 0; j < 10; ++j) arr[0][j][i] = arr[1][j][i] = COMPLEX(0, 0); for(int i = 0; i < len1; ++i) arr[0][str1[i]-'0'][i] = COMPLEX(1, 0); for(int i = 0; i < len2; ++i) arr[1][str2[i]-'0'][i] = COMPLEX(1, 0); for(int i = 0; i <= len2; ++i) rec[i] = 0; for(int i = 0; i < 10; ++i) { FFT(arr[0][i], l, 1); FFT(arr[1][i], l, 1); for(int j = 0; j < l; ++j) arr[0][i][j] = arr[0][i][j]*arr[1][i][j]; FFT(arr[0][i], l, -1); for(int j = len1-1; j < len2; ++j) rec[j] += (int)(arr[0][i][j].a+0.5); } int ans = 0; for(int i = len1-1; i < len2; ++i) checkmax(ans, rec[i]); printf("Case #%d: %d\n", ++n_case, len1-ans); } return 0; }