数论

int cnt,prime[MAXN+1],mi[MAXN+1],vis[MAXN+1];
//cnt表示素数个数
//prime存放每个素数
//mi存放每个数的最小素数因子

void getprime()
{
    cnt = 0;
    memset(prime,0,sizeof(prime));
    for(int i = 2;i <= MAXN;i++)
    {
        if(!vis[i])
        {
            prime[++cnt] = i;
            mi[i] = i;
        }
        for(int j = 1;j <= cnt && (long long)i*prime[j] <= MAXN;j++)
        {
            vis[prime[j]*i] = 1;
            mi[prime[j]*i] = prime[j];
            if(!(i%prime[j]))   break;
        }
    }
}

int cnt2,notprime2[1000005],prime2[1000005];
//区间l,r之间的素数
void getprime2(int l,int r)
{
    cnt2 = 0;
    memset(notprime2,0,sizeof(notprime2));
    if(l < 2)   l = 2;
    for(int i = 1;i <= cnt && (long long)prime[i]*prime[i] <= r;i++)
    {
        int t = l/prime[i];
        if(l%prime[i])  t++;
        if(t == 1)  t = 2;
        for(int j = t;(long long)j*prime[i] <= r;j++)
        {
            if((long long)j*prime[i] >= l)  notprime2[j*prime[i]-l] = 1;
        }
    }
    for(int i = 0;i <= r-l;i++)
    {
        if(!notprime2[i])   prime2[++cnt2] = i+l;
    }
}
素数筛

long long factor[105][2];
//返回素因子个数
//factor[i][0]表示第i个素因子,factor[i][1]表示第i个素因子的个数
int getfac(long long x)
{
    int cnt = 0;
    for(int i = 1;(long long)prime[i]*prime[i] <= x;i++)
    {
        if(x%prime[i] == 0)
        {
            factor[++cnt][0] = prime[i];
            while(x%prime[i] == 0)
            {
                factor[cnt][1]++;
                x /= prime[i];
            }
        }
    }
    if(x != 1)
    {
        factor[++cnt][0] = x;
        factor[cnt][1] = 1;
    }
    return cnt;
}
合数分解

long long qmul(long long a,long long b,long long c)
{
    long long ans = 0;
    a = a%c;
    b = b%c;
    while(b)
    {
        if(b%2)
        {
            ans += a;
            if(ans > c) ans -= c;
        }
        a = a+a;
        if(a > c)   a -= c;
        b /= 2;
    }
    return ans;
}
快速乘

long long qpower(long long a, long long b, long long c)
{
    long long ans = 1;
    a = a%c;
    while(b)
    {
        if(b%2)    ans = ans*a%c;
        a = a*a%c;
        b /= 2;
    }
    return ans;
} 
快速幂
string mul(string a,string b)
{
    int arr[200],len = a.length()+b.length();
    memset(arr,0,sizeof(arr));
    reverse(a.begin(),a.end());
    reverse(b.begin(),b.end());
    for(int i = 0;i < a.length();i++)
    {
        for(int j = 0;j < b.length();j++)   arr[i+j] += (a[i]-'0')*(b[j]-'0');
    }
    for(int i = 0;i < len;i++)
    {
        arr[i+1] += arr[i]/10;
        arr[i] %= 10;
    }
    string ans = string(len,'0');
    for(int i = 0;i < len;i++)  ans[i] += arr[i];
    reverse(ans.begin(),ans.end());
    cout << ans << endl;
    return ans;
}

string strpow(string x,int b)
{
    string ans = "1";
    while(b)
    {
        if(b%2) ans = mul(ans,x);
        x = mul(x,x);
        b /= 2;
    }
    return ans;
}
string快速幂

struct matrix
{
    long long m[2][2];
};

matrix one = {  1,0,
                0,1 };

matrix mul(matrix a, matrix b)
{
    matrix tmp;
    for(int i = 0; i < 2;i++)
    {
        for(int j = 0; j < 2;j++)
        {
            tmp.m[i][j] = 0;
            for(int k = 0; k < 2;k++)   tmp.m[i][j] = (tmp.m[i][j]+a.m[i][k]*b.m[k][j])%MOD;
        }
    }
    return tmp;
}

matrix maqower(matrix a,int b)
{
    matrix ans = one;
    while(b)
    {
        if(b%2) ans = mul(ans,a);
        a = mul(a,a);
        b /= 2;
    }
    return ans;
}
矩阵快速幂

long long qmul(long long a,long long b,long long c)
{
    long long ans = 0;
    a = a%c;
    b = b%c;
    while(b)
    {
        if(b%2)
        {
            ans += a;
            if(ans > c) ans -= c;
        }
        a = a+a;
        if(a > c)   a -= c;
        b /= 2;
    }
    return ans;
}

long long qpower(long long a,long long b,long long c)
{
    long long ans = 1;
    a = a%c;
    while(b)
    {
        if(b%2)    ans = qmul(ans,a,c);
        a = qmul(a,a,c);
        b /= 2;
    }
    return ans;
}

//用a来检验n是否为素数
//是素数返回1,不是返回0
bool check(long long a,long long n,long long x,long long t)
{
    long long ans = qpower(a,x,n);
    if(ans == 1 || ans == n-1)  return 1;
    while(t--)
    {
        ans = qmul(ans,ans,n);
        if(ans == n-1)  return 1;
    }
    return 0;
}

//判断n是否为素数
//是素数返回1,不是返回0
bool miller_rabin(long long n)
{
    if(n < 2)   return 0;
    if(n == 2)  return 1;
    if(n%2 == 0)    return 0;
    long long x = n-1;
    long long t = 0;
    while(x%2 == 0)
    {
        x /= 2;
        t++;
    }
    srand(time(0));
    for(int i = 1;i <= 10;i++)
    {
        long long a = rand()%(n-1)+1;
        if(!check(a,n,x,t))  return 0;
    }
    return 1;
}
miller_rabin判断素数

long long factor[105];
int cnt;

long long gcd(long long a,long long b)
{
    return b?gcd(b,a%b):a;
}

long long pollard_rho(long long n,long long c)
{
    long long i = 1,k = 2;
    srand(time(0));
    long long x = rand()%(n-2)+1,y = x;
    while(1)
    {
        i++;
        x = (qmul(x,x,n)+c)%n;
        long long d = gcd(y-x,n);
        if(1 < d && d < n)  return d;
        if(x == y)  return n;
        if(i == k)
        {
            y = x;
            k *= 2;
        }
    }
}

//求n的质因数,k设为107
void findfac(long long n,int k)
{
    if(n == 1)  return;
    if(miller_rabin(n))
    {
        factor[++cnt] = n;
        return;
    }
    long long p = n;
    int c = k;
    while(p >= n)   p = pollard_rho(p,c--);
    findfac(p,k);
    findfac(n/p,k);
}
pollard_rho分解质因数

LL gcd(LL x,LL y)    //最大公约数
{
    return y?gcd(y,x%y):x;
}

LL lcm(LL x,LL y)    //最小公倍数
{
    return x*y/gcd(x,y);
}
gcd、lcm
//lcm(C(n,0), C(n,1),…, C(n,n)) = lcm(1,2,3,…n+1)/(n+1)
//计算lcm(1,2,3,…n)
const int N=100000007;
int visit[N/32+50];
unsigned int data[5800000];
int prime[5800000],np=0;

void Prime()   //筛素数,数组从0开始
{
    prime[0] = data[0] = 2;
    np = 1;
    for(int i = 3;i < N;i += 2)
    {
        if(!(visit[i/32]&(1<<((i/2)%16))))
        {
            prime[np] = i;
            data[np] = data[np-1]*i;
            np++;
            for(int j = 3*i;j < N;j += 2*i) visit[j/32] |= (1<<((j/2)%16));
        }
    }
}

long long Deal(int n)
{
    int p = upper_bound(prime,prime+np,n)-prime-1;
    long long ans = data[p];
    for (int i = 0;i < np && prime[i]*prime[i] <= n;i++)
    {
        int mul = prime[i],tmp = prime[i] * prime[i];  ;
        while (tmp/mul == prime[i] && tmp <= n)
        {
            tmp *= prime[i];
            mul *= prime[i];
        }
        ans = ans*(mul/prime[i])%MOD;
    }
    return ans;
}
lcm(1,2,3,…n)

欧拉函数:小于N且与N互质的数的个数(包括1)。

对于一个正整数N的素数幂分解N = P1^q1*P2^q2*...*Pn^qn。

φ(N)=N*(1-1/P1)*(1-1/P2)*...*(1-1/Pn)。

//分解质因数
int euler(int n)
{
    int ans = n;
    for(int i = 1;i <= cnt;i++) ans = ans/factor[i][0]*(factor[i][0]-1);
}

long long euler(long long n)  
{  
    long long ans = 1;   
    for(int i = 2;(long long)i*i <= n;i++)  
    {  
        if(n%i == 0)  
        {  
            n /= i;  
            ans *= i-1;  
            while(n%i == 0)  
            {  
                n /= i;  
                ans *= i;  
            }  
        }  
    }  
    if(n > 1)     ans *= n-1;
    return ans;  
}
单个欧拉函数
int cnt,phi[N+10],prime[N+10],vis[N+10];

//同时得到欧拉函数和素数表
void geteuler()
{
    memset(vis,0,sizeof(vis));
    phi[1] = 1;
    cnt = 0;
    for(int i = 2;i <= N;i++)
    {
        if(!vis[i])
        {
            prime[++cnt] = i;
            phi[i] = i-1;
        }
        for(int j = 1;j <= cnt;j++)
        {
            if((long long)i*prime[j] > N)   break;
            vis[i*prime[j]] = 1;
            if(i%prime[j] == 0)
            {
                phi[i*prime[j]] = phi[i]*prime[j];
                break;
            }
            else    phi[i*prime[j]] = phi[i]*(prime[j]-1);
        }
    }
}
线性筛

lucas定理:

A、B是非负整数,p是质数。AB写成p进制:A=a[n]a[n-1]...a[0],B=b[n]b[n-1]...b[0]。
则组合数C(A,B)与C(a[n],b[n])*C(a[n-1],b[n-1])*...*C(a[0],b[0])  modp同余。

即:Lucas(n,m,p)=c(n%p,m%p)*Lucas(n/p,m/p,p) 。

//用与n,m很大,MOD不是很大的情况
long long qmod(long long a,long long b,long long c)
{
    long long ans = 1;
    a = a%c;
    while(b)
    {
        if(b%2)  ans = (ans*a)%c;
        a = (a*a)%c;
        b /= 2;
    }
    return ans;
}

long long c(long long m,long long n)
{
    if(m < n)   return 0;
    if(m == n)  return 1;
    if(n > m-n) n = m-n;
    long long mm = 1,nn = 1;
    for(long long i = 0;i < n;i++)
    {
        mm = mm*(m-i)%MOD;
        nn = nn*(n-i)%MOD;
    }
    return mm*qmod(nn,MOD-2,MOD)%MOD;
}

long long lucas(long long m,long long n)
{
    long long ans = 1;
    while(m && n && ans)
    {
        ans = ans%MOD*c(m%MOD,n%MOD)%MOD;
        n /= MOD;
        m /= MOD;
    }
    return ans;
}
lucas
long long inv(long long a,long long MOD)
{
    if(!a)  return 0;
    long long b = MOD,x = 0,y = 0;
    e_gcd(a,b,x,y);
    x = ((x%b)+b)%b;
    if(!x)  x += b;
    return x;
}

long long mul(long long n,long long pi,long long pk)
{
    if(!n)  return 1;
    long long ans=1;
    for(long long i = 2;i <= pk;i++)
    {
        if(i%pi)    ans = ans*i%pk;
    }
    ans = qpower(ans,n/pk,pk);
    for(long long i = 2;i <= n%pk;i++)
    {
        if(i%pi)    ans = ans*i%pk;
    }
    return ans*mul(n/pi,pi,pk)%pk;
}

long long C(long long n,long long m,long long MOD,long long pi,long long pk)
{
    if(m > n)   return 0;
    long long a = mul(n,pi,pk),b = mul(m,pi,pk),c = mul(n-m,pi,pk),k = 0,ans = 0;
    for(long long i = n;i;i /= pi)  k += i/pi;
    for(long long i = m;i;i /= pi)  k -= i/pi;
    for(long long i = n-m;i;i /= pi)    k -= i/pi;
    ans = a*inv(b,pk)%pk*inv(c,pk)%pk*qpower(pi,k,pk)%pk;
    return ans*(MOD/pk)%MOD*inv(MOD/pk,pk)%MOD;
}


long long lucas(long long n,long long m,long long MOD)
{
    long long ans = 0,x = MOD;
    for(long long i = 2;i*i <= x;i++)
    {
        if(x%i == 0)
        {
            long long t = 1;
            while(x%i == 0)
            {
                t *= i;
                x /= i;
            }
            ans = (ans+C(n,m,MOD,i,t))%MOD;
        }
    }
    if(x > 1)   ans = (ans+C(n,m,MOD,x,x))%MOD;
    return ans;
}
扩展lucas(模合数)

费马小定理:假如p是素数,且a与p互质,那么a^(p-1) = 1 (mod p)。

费马大定理:当整数n>2时,关于 x,y,z的方程x^n+y^n=z^n没有正整数解。

欧拉定理:若n,a为正整数,且n,a互质,则:a^(phi(n)) = 1(mod n)

                  可得a^b%p = a^(b%phi(p))%p

另外,a,b不互质且b<phi(n)时,有 a^b%p = a^(b%phi(p)+phi(p))%p


逆元:ax = 1(mod m)的x值(0 < a < m)。

当p是质数的时候 a/x mod p == a*x^(p-2) mod p 。

当p不是质数的时候a/x mod p == a*x^(phi(p)-1) mod p。

//a,m互质
long long inv(long long a,long long m)
{
    return qmod(a,m-2,m);
}
逆元1
//a < m且a,m互质
long long inv(long long a,long long m)
{
    if(a == 1)  return 1;
    return inv(m%a,m)*(m-m/a)%m;
}
逆元2
//a,m互质
//扩展欧几里德
long long e_gcd(long long a,long long b,long long &x,long long &y)
{
    if(!b)
    {
        x = 1;
        y = 0;
        return a;
    }
    long long d = e_gcd(b,a%b,y,x);
    y -= a/b*x;
    return d;
}

long long inv(long long a,long long m)
{
    long long x,y;
    long long gcd = e_gcd(a,m,x,y);
    if(gcd == 1)    return (x%m+m)%m;
    return -1;
}
逆元3

//求解方程组x%m = a,x的最小值
//无解返回-1
long long e_gcd(long long a,long long b,long long &x,long long &y)
{
    if(!b)
    {
        x = 1;
        y = 0;
        return a;
    }
    long long d = e_gcd(b,a%b,y,x);
    y -= a/b*x;
    return d;
}

long long solve(long long *m,long long *a,long long n)
{
    long long M = m[1],A = a[1],x,y;
    for(int i = 2;i <= n;i++)
    {
        long long d = e_gcd(M,m[i],x,y);
        if((a[i]-A)%d)  return -1;
        x = (a[i]-A)/d*x%(m[i]/d);
        A += x*M;
        M = M/d*m[i];
        A %= M;
    }
    if(A < 0)   A += M;
    return A;
}
中国剩余定理

//浮点型只有唯一解时可计算
//返回0表示无解
#define eps 1e-9
double a[N][N],x[N];        //左边矩阵和右边值,结果存在x数组内
int Gauss(int equ,int var)  //方程个数和未知数个数
{
    for(int row = 0,col = 0;col < var&&row < equ;col++,row++)
    {
        int max_r=row;
        for(int i = row+1;i < equ;i++)
        {
            if(fabs(a[i][col])-fabs(a[max_r][col]) > eps)   max_r=i;
        }
        if(fabs(a[max_r][col]) < eps)   return 0;
        if(max_r != row)
        {
            for(int j = 0;j <= var;j++) swap(a[row][j],a[max_r][j]);
        }
        for(int i = row+1;i < equ;i++)
        {
            if(fabs(a[i][col]) < eps)   continue;
            double t = -a[i][col]/a[row][col];
            for(int j = col;j <= var;j++)   a[i][j] += t*a[row][j];
        }
    }
    for(int i = var-1;i >= 0;i--)   //计算唯一解。
    {
        double t = 0;
        for(int j = i+1;j < var;j++)    t += a[i][j]*x[j];
        x[i] = (a[i][var]-t)/a[i][i];
    }
    return 1;
}
浮点数高斯消元
#include<bits/stdc++.h>
using namespace std;

//POJ1681
//有equ个方程,var个变元。增广矩阵行数为equ,分别为0到equ-1,列数为var+1,分别为0到var.
int equ,var;
int a[250][250];    //增广矩阵
int x[250];         //解集
int free_x[250];    //标记是否不确定的变元
int free_num;       //不确定变元个数
int n;
char s[30];
//-1表示无解,0表示唯一解,大于0表示无穷解,并返回自由变元的个数)
void init()
{
    memset(a,0,sizeof(a));
    memset(x,0,sizeof(x));
    equ = n*n;
    var = n*n;
    for(int i = 0;i < n;i++)
    {
        for(int j = 0;j < n;j++)
        {
            int t = i*n+j;
            a[t][t] = 1;
            if(i > 0)   a[(i-1)*n+j][t] = 1;
            if(i < n-1) a[(i+1)*n+j][t] = 1;
            if(j > 0)   a[i*n+j-1][t] = 1;
            if(j < n-1) a[i*n+j+1][t] = 1;
        }
    }
}

void Debug()
{
    for(int i = 0;i < equ;i++)
    {
        for(int j = 0;j < var+1;j++)  cout << a[i][j] << " ";
        cout << endl;
    }
    cout << endl;
}

int Gauss()
{
    int max_r,col,k;
    free_num = 0;
    for(k = 0,col = 0;k < equ && col < var;k++,col++)
    {
        max_r = k;
        for(int i = k+1;i < equ;i++)
        {
            if(abs(a[i][col]) > abs(a[max_r][col])) max_r = i;
        }
        if(max_r != k)
        {
            for(int i = col;i < var+1;i++)  swap(a[k][i],a[max_r][i]);
        }
        if(a[k][col] == 0)
        {
            k--;
            free_x[free_num++] = col;
            continue;
        }
        for(int i = k+1;i < equ;i++)
        {
            if(a[i][col] == 0)  continue;
            for(int j = col;j < var+1;j++)  a[i][j] ^= a[k][j];
        }
    }
    for(int i = k;i < equ;i++)
    {
        if(a[i][col] != 0)  return -1;
    }
    return var-k;
}

void solve()
{
    int t = Gauss();
    if(t == -1) printf("inf\n");
    else
    {
        int ans = INT_MAX,tot = (1<<t);
        for(int i = 0;i < tot;i++)
        {
            int cnt = 0;
            for(int j = 0;j < t;j++)
            {
                if(i&(1<<j))
                {
                    x[free_x[j]] = 1;
                    cnt++;
                }
                else    x[free_x[j]] = 0;
            }
            for(int j = var-t-1;j >= 0;j--)
            {
                int t = a[j][var];
                for(int k = j+1;k < var;k++)
                {
                    if(a[j][k]) t ^= x[k];
                }
                x[j] = t;
                cnt += x[j];
            }
            ans = min(ans,cnt);
        }
        printf("%d\n",ans);
    }
}

int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d",&n);
        init();
        for(int i = 0;i < n;i++)
        {
            scanf("%s",s);
            for(int j = 0;j < n;j++)
            {
                if(s[j] == 'y') a[i*n+j][n*n] = 0;
                else    a[i*n+j][n*n] = 1;
            }
        }
        solve();
    }
    return 0;
}
01异或高斯消元
int a[MAXN][MAXN];  //增广矩阵
int x[MAXN];        //解集
bool free_x[MAXN];  //标记是否是不确定的变元

int gcd(int a,int b)
{
    return b?gcd(b,a%b):a;
}
int lcm(int a,int b)
{
    return a/gcd(a,b)*b;
}

//-1表示无解,0表示唯一解,大于0表示无穷解,并返回自由变元的个数)
//有equ个方程,var个变元。增广矩阵行数为equ,分别为0到equ-1,列数为var+1,分别为0到var.
int Gauss(int equ,int var)
{
    int i,j,k;
    int max_r;// 当前这列绝对值最大的行.
    int col;//当前处理的列
    int ta,tb;
    int LCM;
    int temp;
    int free_x_num;
    int free_index;
    for(int i = 0;i <= var;i++)
    {
        x[i]=0;
        free_x[i]=true;
    }
    col=0;
    for(k = 0;k < equ && col < var;k++,col++)
    {
        max_r=k;
        for(i = k+1;i < equ;i++)
        {
            if(abs(a[i][col]) > abs(a[max_r][col])) max_r=i;
        }
        if(max_r != k)
        {
            for(j = k;j < var+1;j++)    swap(a[k][j],a[max_r][j]);
        }
        if(a[k][col] == 0)
        {
            k--;
            continue;
        }
        for(i = k+1;i < equ;i++)
        {
            if(a[i][col] != 0)
            {
                LCM = lcm(abs(a[i][col]),abs(a[k][col]));
                ta = LCM/abs(a[i][col]);
                tb = LCM/abs(a[k][col]);
                if(a[i][col]*a[k][col] < 0) tb = -tb;
                for(j = col;j < var+1;j++)
                {
                    a[i][j] = ((a[i][j]*ta-a[k][j]*tb)%7+7)%7;
                }
            }
        }
    }
    for(i = k; i < equ; i++)
    {
        if (a[i][col] != 0) return -1;
    }
    if(k < var)
    {
        for(i = k-1;i >= 0;i--)
        {
            free_x_num = 0;
            for(j = 0;j < var;j++)
            {
                if (a[i][j] != 0 && free_x[j])  free_x_num++,free_index = j;
            }
            if(free_x_num > 1)  continue;
            temp = a[i][var];
            for(j = 0;j < var;j++)
            {
                if(a[i][j] != 0 && j != free_index) temp -= a[i][j]*x[j]%7;
                temp = (temp%7+7)%7;
            }
            x[free_index] = (temp/a[i][free_index])%7;
            free_x[free_index] = 0;
        }
        return var-k;
    }
    for(i = var-1;i >= 0;i--)
    {
        temp = a[i][var];
        for (j = i + 1;j < var;j++)
        {
            if(a[i][j] != 0)    temp -= a[i][j]*x[j];
            temp = (temp%7+7)%7;
        }
        while(temp%a[i][i] != 0)    temp += 7;
        x[i] =(temp/a[i][i])%7;
    }
    return 0;
}
同余方程组高斯消元

#include<bits/stdc++.h>
#define N 262145
#define PI acos(-1)
using namespace std;

typedef complex<double> C;
int n,m;
C a[N],b[N];

int gi()
{
    int res = 0,fh = 1;
    char ch = getchar();
    while((ch > '9' || ch < '0') && ch != '-')  ch = getchar();
    if(ch == '-')
    {
        fh=-1;
        ch=getchar();
    }
    while(ch >= '0' && ch <= '9')
    {
        res = res*10+ch-'0';
        ch=getchar();
    }
    return fh*res;
}

void fft(C *a,int n,int f)
{
    if(n == 1)  return;
    C wn(cos(2.0*PI/n),sin(f*2.0*PI/n)),w(1,0),t,a0[n>>1],a1[n>>1];
    for(int i = 0;i < n>>1;i++)
    {
        a0[i] = a[i<<1];
        a1[i] = a[i<<1|1];
    }
    fft(a0,n>>1,f);
    fft(a1,n>>1,f);
    for(int i = 0;i < n>>1;i++,w *= wn)
    {
        t = w*a1[i];
        a[i] = a0[i]+t;
        a[i+(n>>1)] = a0[i]-t;
    }
}
int main()
{
    n = gi();
    m = gi();
    for(int i = 0;i <= n;i++)   a[i]=gi();
    for(int i = 0;i <= m;i++)   b[i]=gi();
    m += n;
    for(n = 1;n <= m;n *= 2);
    fft(a,n,1);
    fft(b,n,1);
    for(int i = 0;i <= n;i++)   a[i] *= b[i];
    fft(a,n,-1);
    for(int i = 0;i <= m;i++)   printf("%d ",int(a[i].real()/n+0.5));
    return 0;
}
FFT递归
#include<bits/stdc++.h>
#define N 262145
#define PI acos(-1)
using namespace std;

typedef complex<double> C;
int n,m,L,R[N];
C a[N],b[N];

int gi()
{
    int res = 0,fh = 1;
    char ch = getchar();
    while((ch > '9' || ch < '0') && ch != '-')  ch = getchar();
    if(ch == '-')
    {
        fh=-1;
        ch=getchar();
    }
    while(ch >= '0' && ch <= '9')
    {
        res = res*10+ch-'0';
        ch=getchar();
    }
    return fh*res;
}


void fft(C *a,int f)
{
    for(int i = 0;i < n;i++)
    {
        if(i < R[i])    swap(a[i],a[R[i]]);
    }
    for(int i = 1;i < n;i *= 2)
    {
        C wn(cos(PI/i),sin(f*PI/i)),x,y;
        for(int j = 0;j < n;j += i<<1)
        {
            C w(1,0);
            for(int k = 0;k < i;k++,w *= wn)
            {
                x = a[j+k];
                y = w*a[j+i+k];
                a[j+k] = x+y;
                a[j+i+k] = x-y;
            }
        }
    }
}

int main()
{
    n = gi();
    m = gi();
    for(int i = 0;i <= n;i++)   a[i] = gi();
    for(int i = 0;i <= m;i++)   b[i] = gi();
    m += n;
    for(n = 1;n <= m;n *= 2)    L++;
    for(int i = 0;i < n;i++)    R[i] = (R[i>>1]>>1)|((i&1)<<(L-1));
    fft(a,1);
    fft(b,1);
    for(int i = 0;i <= n;i++)   a[i] *= b[i];
    fft(a,-1);
    for(int i = 0;i <= m;i++)   printf("%d ",int(a[i].real()/n+0.5));
    return 0;
}
FFT非递归

//需要getprime,qpower,getfac,先调用getprime
//计算1+p+p^2+````+p^n
long long sum(long long p,long long n)
{
    if(p == 0)  return 0;
    if(n == 0)  return 1;
    if(n%2) return (1+qpower(p,n/2+1,MOD))%MOD*sum(p,n/2)%MOD;
    else    return ((1+qpower(p,n/2+1,MOD))%MOD*sum(p,n/2-1)+qpower(p,n/2,MOD)%MOD)%MOD;
}

//求a^b的约数和对MOD取模
long long solve(long long a,long long b)
{
    int cnt = getfac(a);
    long long ans = 1;
    for(int i = 1;i <= cnt;i++)
    {
        ans *= sum(factor[i][0],b*factor[i][1])%MOD;
        ans %= MOD;
    }
    return ans;
}
约数和定理

莫比乌斯反演:

#include<bits/stdc++.h>
using namespace std;

const int MAXN = 100000;
bool check[MAXN+5];
int prime[MAXN+5],mu[MAXN+5],sum[MAXN+5];

//求莫比乌斯函数
void Moblus()
{
    memset(check,0,sizeof(check));
    mu[1] = 1;
    int cnt = 0;
    for(int i = 2;i <= MAXN;i++)
    {
        if(!check[i])
        {
            prime[cnt++] = i;
            mu[i] = -1;
        }
        for(int j = 0;j < cnt && i*prime[j] <= MAXN;j++)
        {
            check[i*prime[j]] = 1;
            if(i%prime[j] == 0)
            {
                mu[i*prime[j]] = 0;
                break;
            }
            else    mu[i*prime[j]] = -mu[i];
        }
    }
    sum[0] = 0;
    for(int i = 1;i <= MAXN;i++)    sum[i] = sum[i-1]+mu[i];
}

//求[1,n],[1,m]内互质的数的对数
int solve(int n,int m)
{
    int ans = 0;
    if(n > m)   swap(n,m);
    for(int i = 1,last;i <= n;i = last+1)
    {
        last = min(n/(n/i),m/(m/i));
        ans += (sum[last]-sum[i-1])*(n/i)*(m/i);
    }
    return ans;
}

int main()
{
    Moblus();
    int a,b,c,d,k,T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d%d%d%d",&a,&b,&c,&d,&k);
        a--;
        c--;
        a /= k;
        b /= k;
        c /= k;
        d /= k;
        printf("%d\n",solve(b,d)-solve(a,d)-solve(b,c)+solve(a,c));
    }

}
莫比乌斯反演

#include<bits/stdc++.h>
using namespace std;

int gcd(int a, int b )
{
    return b == 0?a:gcd(b,a%b);
}

long long qpower(long long a, long long b, long long c)
{
    long long ans = 1;
    a = a%c;
    while(b)
    {
        if(b%2)    ans = ans*a%c;
        a = a*a%c;
        b /= 2;
    }
    return ans;
}

long long e_gcd(long long a,long long b,long long &x,long long &y)
{
    if(!b)
    {
        x = 1;
        y = 0;
        return a;
    }
    long long d = e_gcd(b,a%b,y,x);
    y -= a/b*x;
    return d;
}

int Inval(int a,int b,int n)
{
    long long x, y, e;
    e_gcd(a,n,x,y);
    e = (long long)x*b%n;
    return e < 0?e+n:e;
}

//求A^x = B(mod C)(C可以为非素数)
int BSGS(int A,int B,int C)
{
    map<int,int> H;
    long long buf = 1%C,D = buf,K;
    int d = 0,tmp;
    for (int i = 0;i <= 100;buf = buf*A%C,i++)
    if(buf == B)    return i;
    while((tmp = gcd(A,C)) != 1)
    {
        if(B % gcd(A,C)!= 0)    return -1;
        d++;
        C /= tmp;
        B /= tmp;
        D =D*A/tmp%C;
    }
    H.clear();
    int M = (int)ceil(sqrt(C));
    buf = 1%C;
    for(int i = 0;i <= M;buf = buf*A%C,i++)
    {
        if(H.find((int)buf) == H.end()) H[(int)buf] = i;
    }
    K = qpower(A,M,C);
    for(int i = 0;i <= M;D = D*K%C,i++)
    {
        tmp = Inval((int)D,B,C);
        if(tmp >= 0 && H.find(tmp) != H.end())  return i*M+H[tmp]+d;
    }
    return -1;
}
BSGS

const double eps = 1e-6;
// 三点simpson法。这里要求F是一个全局函数
double simpson(double a,double b)
{
    double c = a+(b-a)/2;
    return (F(a)+4*F(c)+F(b))*(b-a)/6;
}
// 自适应Simpson公式(递归过程)。已知整个区间[a,b]上的三点simpson值A
double asr(double a,double b,double eps,double A)
{
    double c = a+(b-a)/2;
    double L = simpson(a,c),R = simpson(c,b);
    if(fabs(A-L-R) <= 15*eps)   return L+R+(A-L-R)/15;
    return asr(a,c,eps/2,L)+asr(c,b,eps/2,R);
}
// 自适应Simpson公式(主过程)
double asr(double a,double b,double eps)
{
    return asr(a,b,eps,simpson(a,b));
}
自适应simpson积分

康托展开:

X = an*(n-1)!+an-1*(n-2)!+...+ai*(i-1)!+...+a2*1!+a1*0!

其中,ai为当前未出现的元素中是排在第几个(从0开始)。

int f(vector<int> v)
{
    int sum = 0;
    for(int i = 0;i < 8;i++)
    {
        int t = 0;
        for(int j = i+1;j < 8;j++)
        {
            if(v[i] > v[j]) t++;
        }
        sum += t*h[7-i];
    }
    return sum;
}
康托展开

//f[]:可以取走的石子个数
//sg[]:0~n的SG函数值
//hash[]:mex{}
int n,m,p,f[N],sg[N],hashh[N]; 
    
void getSG(int n)
{
    memset(sg,0,sizeof(sg));
    for(int i = 1;i <= n;i++)
    {
        memset(hashh,0,sizeof(hashh));
        for(int j = 1;f[j] <= i;j++)    hashh[sg[i-f[j]]] = 1;
        for(int j = 0;j <= n;j++)        //求mes{}中未出现的最小的非负整数
        {
            if(hashh[j] == 0)
            {
                sg[i] = j;
                break;
            }
        }
    }
}
sg函数

1. 若划分的多个整数可以相同

设dp[i][j]为将i划分为不大于j的划分数。

(1) 当i<j 时,i不能划分为大于i的数,dp[i][j]=dp[i][i]。

(2) 当i>j 时,可以根据划分中是否含有j分为两种情况。

  若划分中含有j,划分方案数为dp[i-j][j]。

  若划分数中不含j,相当于将i划分为不大于j-1的划分数,为dp[i][j-1]。

  所以当i>j时,dp[i][j]=dp[i-j][j]+dp[i][j-1]。

(3) 当i=j 时,若划分中含有j只有一种情况,若划分中不含j相当于将i划分为不大于j-1的划分数。此时dp[i][j]=1+dp[i][j-1]。


2.将n划分为k个整数的划分数

dp[i][j]表示将i划分成j个正整数的划分数。

(1) 当i<j时,i不能划分成j个正整数,dp[i][j]=0。

(2) 当i=j时,只有一种情况,dp[i][j]=1。

(3) 当i>j时, 此时根据含1和不含1,故dp[i][j]=dp[i-1][j-1]+dp[i-j][j]。


3. 若划分的正整数必须不同

设dp[i][j]为将i划分为不超过j的不同整数的划分数。

(1) 当i<j时,i不能划分为大于i的数,所以dp[i][j]=dp[i][i]。

(2) 当i>j时,可以根据划分中是否含有j分为两种情况。

  若划分中含有j,则其余的划分中最大只能是j-1,方案数为dp[i-j][j-1]。

  若划分中不含j,相当于将i划分为不大于j-1的划分数,为dp[i][j-1]。

  所以当i>j时dp[i][j]=dp[i-j][j-1]+dp[i][j-1]。

(3) 当i=j时,若划分中含有j只有一种情况,若划分中不含j相当于将i划分为不大于j-1的划分数。此时dp[i][j]=1+dp[i][j-1]。

 
4.将n划分为若干正奇数之和的划分数

设f[i][j]为将i划分为j个奇数之和的划分数,g[i][j]为将i划分为j个偶数之和的划分数。

使用截边法,将g[i][j]的j个划分都去掉1,可得g[i][j] = f[i-j][j]。

f[i][j]中有包含1的划分方案和不包含1的划分方案。

  对于包含1的划分方案,可以将1的划分除去,转化为“将i-1划分为j-1个奇数之和的划分数”,即f[i-1][j-1]。

  对于不包含1的划分方案,可以使用截边法对j个划分每一个都去掉一个1,转化为“将i-j划分为j个偶数之和的划分数”,即g[i-j][j]。

  所以f[i][j]=f[i-1][j-1]+g[i-j][j]。

f[n][0]+f[n][1]+……+f[n][n]为将n划分为若干奇数的划分数。
整数划分分类

Polya定理:设 G = {a1,a2,…,ag}是 N 个对象的置换群,用 M 种颜色给这 N 个对象着色,

则不同的着色 方案数为:|G|^(-1) * {M^c(a1) + M^c(a2) + … + M^c(ag)}。其中 c(ai)为置换 ai 的循环节数,( i = 1,2,…,g )。


设m是正整数,a是整数,若a模m的阶等于φ(m),则称a为模m的一个原根。

如果g是P的原根,那么g的(1...P-1)次幂mod P的结果一定互不相同。

如果g是P的原根,就是g^(P-1) = 1 (mod P)当且仅当指数为P-1的时候成立.(这里P是素数).

int n,a[35000],cnt = 0;

LL qmod(LL a, LL b, LL c)
{
    LL ans = 1;
    a = a%c;
    while(b)
    {
        if(b&1)    ans = ans*a%c;
        b >>= 1;
        a = a*a%c;
    }
    return ans;
}

int main()
{
    scanf("%d",&n);
    int endd = sqrt(n-1);
    for(int i = 2;i <= endd;i++)
    {
        if((n-1)%i == 0)    a[++cnt] = i;
    }
    for(int i = 2;i <= n-1;i++)
    {
        int j;
        for(j = 1;j <= cnt;j++)
        {
            if(qmod(i,a[j],n) == 1 || qmod(i,(n-1)/a[j],n) == 1)    break;
        }
        if(j == cnt+1)
        {
            printf("%d\n",i);
            return 0;
        }
    }
}
求原根

卡特兰数 1, 2, 5, 14, 42

h(0) = 1,h(1) = 1

h(n) = h(0)*h(n-1)+h(1)*h(n-2) + ... + h(n-1)h(0) (n>=2)

h(n) = h(n-1)*(4*n-2)/(n+1)

h(n) = C(2n,n)/(n+1) 

h(n) = C(2n,n)-C(2n,n-1)

1.n对括号正确匹配组成的字符串数。

2.一个栈(无穷大)的进栈序列为1,23,…,n,有多少个不同的出栈序列。

3.在一个凸多边形中,通过若干条互不相交的对角线,把这个多边形划分成了若干个三角形,求不同划分的方案数f(n)。

4.一位大城市的律师在她住所以北n个街区和以东n个街区处工作。

5.长度为 2n的 Dyck words的数量。 Dyck words是由 n个 X和 n个 Y组成的字符串,并且从左往右数, Y的数量不超过 X。

6.拥有 n+1 个叶子节点的二叉树的数量。例如 4个叶子节点的所有二叉树形态。

7.圆桌握手问题: 圆桌周围有 2n个人,他们两两握手,但没有交叉的方案数。
卡特兰数

调和级数

f(n)ln(n)+C+1/2*n    (n很大时)

C≈0.57721566490153286060651209


 

posted @ 2017-09-02 22:37  zzzzzzzzhu  阅读(278)  评论(0编辑  收藏  举报