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;
}