练一练,小模版练手

单求欧拉函数

ll phi(ll n)
{
    ll ans = n;
    for(int i = 2; i * i <= n; i++)
    {
        if(n % i == 0)
        {
            ans -= ans / i;
            while(n % i == 0)
                n /= i;
        }
    }
    if(n > 1) ans -= ans / n;
    return ans; 
}

欧拉函数线性筛

void euler()
{
    phi[1] = 1;
    for(int i = 2; i < maxn; i++)
    {
        phi[i] = i;
    }
    for(int i = 2; i <= maxn; i++)
    {
        if(phi[i] == i)
            for(int j = i; j < maxn; j += i)
            phi[j] = phi[j] /i *  (i - 1);
    }
}

性质:
1.添加链接描述
素数筛线性筛

const int maxn =1e6 + 7;

int tot;
bool valid[maxn];
int prime[maxn];

void getPrime()
{
    memset(valid, true, sizeof(valid));
    valid[1] = valid[1] = false;
    tot = 0;
    for(int i = 2; i < maxn; i++)
    {
        if(valid[i])
            prime[tot++] = i;
        for(int j = 1; j < tot && i * prime[j] < maxn; j++)
        {
            valid[i * prime[j]] = false;
            if(i % prime[j] == 0) break;
        }
    }
}
//用线性筛求莫比乌斯函数
void getmiu()
{
    tot = 0;
    memset(valid, true, sizeof(valid));
    valid[0] = valid[1]  = false;
    miu[1] = 1;
    sumu[1] = 1;
    for(int i = 2; i < maxn; i++)
    {
        if(valid[i])
        {
            prime[tot++] = i;
            miu[i] = -1;
        }
        for(int j = 0; j < tot && prime[j] * i < maxn; j++)
        {
            valid[prime[j] * i] = false;
            if(i % prime[j] == 0)
            {
                miu[i * prime[j]] = 0;
                break;
            }
            else
                miu[i * prime[j]] = -miu[i];
        }
        sumu[i] = sumu[i - 1] + miu[i];
    }
}

扩展欧几里得

int exgcd(int a, int b, int &x, int &y)
{
    if(b == 0)
    {
        x = 1, y = 0;
        return a;
    }
    int r = exgcd(b, a % b, y, x);
    y -= x * (a / b);
    return r;
}


解方程组 ax + by = c % b, c 为gcd(a, b) 的倍数
扩展kmp

char s[maxn], t[maxn];
int exend[maxn], exnext[maxn];

void getNext(char *t)
{
    int len = strlen(t);
    exnext[0] = len;
    int p = 0, a = 0;
    for(int i = 1; i < len; i++)
    {
        if(i >= p || i + exnext[i - a] >= p)
        {
            if(i >= p)
                p = i;
            while(p < len && t[p] == t[p - i])
                p++;
            a = i;
            exnext[i] = p - i;
        }
        else
            exnext[i] = exnext[i - a];
    }
}

void exkmp(char *s, char *t)
{
    int m = strlen(t);
    int n = strlen(s);
    getNext(t);
    int p = 0, a = 0;
    for(int i = 0; i < n; i++)
    {
        if(i >= p || exnext[i - a] + i>= p)
        {
            if(i >= p)
                p = i;
            while(p - i < m && p < n && t[p - i] == s[p])next
                p++;
            a = i;
            exend[i] = p - i;
        }
        else
            exend[i] = exnext[i - a];
    }
    
}

kmp

void getnext(int n)
{
   int k = -1, j = 0;
   nex[0] = -1;
   while(j < n)
   {
       if(k == -1 || p[k] == p[j])
       {
           j++, k++;
           if(p[k] != p[j]) nex[j] = k;
           else nex[j] = nex[k];
       }
       else
       k = nex[k];
   }
}

int kmp(int n, int m)
{
     int j = 0, i = 0;
     while(i < n && j < m)
     {
          if(j == -1 || p[j] == s[i])
          {
              i++, j++;
          }
          else j = nex[j];
     }
     if(j == m)
     return i - m + 1;
     else return -1;
}

马拉车

char s[maxn];
int p[maxn<<1];
char man[maxn<<1];

int init(char *s)
{
    int len = strlen(s);
    man[0] = '$';
    man[1] = '#';
    int j = 2;
    for(int i = 0; i < len; i++)
    {
        man[j++] = s[i];
        man[j++] = '#';
    }
    man[j] = 0;
    return j;
}

void manacher(char *s)
{
    int len = init(s);
    int mx = 0, id;
    for(int i = 1; i < len; i++)
    {
        if(i < mx)
        p[i] = min(mx - i, p[2 * id - i]);
        else
            p[i] = 1;
        while(man[i + p[i]] == man[i - p[i]])
            p[i]++;
        if(i + p[i] > mx)
        {
            id = i;
            mx = i + p[i];
        }
    }

}

分块

void build(int n)
{
    int block = sqrt(n);
    int num = n / block;
    if(n % block) num++;
    for(int i = 1; i <= num; i++)
    {
        l[i] = (i - 1) * block + 1;
        r[i] =  i * block;
    }
    r[num] = n;
    for(int i = 1; i <= num; i++)
        for(int j = l[i]; j <= r[i]; j++)
        belong[j] = i;
}

void update(int x, int y)
{
    if(belong[x] == belong[y])
    {
        for(int i = x; i <= y; i++)
            a[i]++;
    }
    else
    {
        for(int i = x; i <= r[belong[x]]; i++)
        {
            a[i]++;
        }
        for(int i = belong[x] + 1; i < belong[y]; i++)
            time[i]++;
        for(int i = l[belong[y]]; i <= y; i++)
            a[i]++;
    }
}

快速幂和龟速乘(两者结合加速防爆炸)

ll q_pow(ll x, ll y, ll mod)
{
    ll sum = 1;
    while(y)
    {
        if(y & 1) sum = (sum * x) % mod;
        x = x * x % mod;
        y >>= 1;
    }
    return sum;
}

ll q_mul(ll x, ll y, ll mod)
{
    ll ans = 0;
    while(y)
    {
        if(y & 1) ans += x, ans %= mod;
        x = x + x;
        x %= mod;
        y >>= 1;
    }
    return ans;
}

卢卡斯

ll lucas(ll n, ll m,ll mod)
{
    if(m == 0)
        return 1;
    return C(n % mod, m % mod, mod) * lucas(n / mod, m / mod, mod) % mod;
}

中国剩余定理


ll crt(ll m[], ll a[], int n)
{
     ll M = 1, ans = 0, x, y, Mi;
     for(int i = 1; i <= n; i++)
        M *= m[i];
     for(int i = 1; i <= n; i++)
     {
         Mi = M / m[i];
         exgcd(Mi, m[i], x, y);
         x = (x % m[i] + m[i]) % m[i];
         ans = (ans + a[i] * Mi * x) % M;
     }
     return (ans % M + M) % M;
}

中国剩余定理非互质

typedef long long ll;

ll m[maxn], a[maxn];

ll exgcd(ll a, ll b, ll &x, ll &y)
{
    if(!b)
    {
        x = 1, y = 0;
        return a;
    }
    ll r = exgcd(b, a % b, y, x);
    y -= x * (a / b);
    return r;
}

ll excrt(ll m[], ll a[], int n)
{
     ll M = m[1], c = a[1], x, y, gcd;
     for(int i = 2; i <= n; i++)
     {
         gcd = exgcd(M,m[i], x, y);
         if((a[i] - c) % gcd) return -1;
         x = (a[i] - c) / gcd * x % m[i];
         c = c + M * x;
         M = M / gcd * m[i];
         c %= M;
     }
     return (c % M + M) % M;
}


int main()
{
    int n;
    while(~scanf("%d", &n))
    {
        for(int i = 1; i <= n; i++)
        {
            scanf("%lld%lld", m + i, a + i);
        }
        ll ans = excrt(m, a, n);
        printf("%lld\n", ans);
    }
    return 0;
}

st表、

int a[maxn];
int st[maxn][30];

void init(int n)
{
    for(int i = 0; i < n; i++)
        st[i][0] = a[i];
    for(int j = 1; (1 << j) <= n; j++)
    {
        for(int i = 0; i + (1 << j) - 1 < n; i++)
            st[i][j] = min(st[i][j - 1], st[i + (1 << (j - 1)][j - 1]);
    }
}

int get(int l, int r)
{
    int k = (int)(log(r - l + 1)/ log(2.0));
    return min(st[l][k], st[r - (1 << k) + 1][k]);
}

矩阵快速幂

typedef long long ll;
const int mod = 1e9 + 7;

ll fast_mul(ll a, ll b)
{
    ll res = 0;
    while(b)
    {
        if(b & 1) res = (res + a) % mod;
        a = (a + a) % mod;
        b >>= 1;
    }
    return res;
}

struct marx
{
    ll mar[2][2];
    marx()
    {
        for(int i = 0; i < 2; i++)
        {
            for(int j = 0; j < 2; j++)
            {
                mar[i][j] = 0;
            }
            mar[i][i] = 1;
        }
    }
    marx operator * (const &a)
    {
        marx res;
        for(int i = 0, i < 2; i++)
        {
            for(int j = 0; j < 2; j++)
            {
                int sum = 0;
                for(int k = 0; k < 2; k++)
                {
                    sum = (sum + fast_mul(mar[i][k], a.mar[k][j])) % mod;
                }
                res.mar[i][j] = sum;
            }
        }
        return res;
    }
};

匈牙利算法

bool hungry(int x)
{
    for(int i = m + 1; i <= n; i++)
    {
        if(!mp[x][i]) continue;
        if(!used[i])
        {
            used[i] = true;
            if(!_pair[i] || hungry(_pair[i]))
            {
                _pair[i] = x;
               // printf("21213\n");
                return true;
            }
        }
    }
    return false;
}

    for(int i = 1; i <= n; i++)
    {
        memset(used, false, sizeof(used));
        if(hungry(i))
        ans++;
    }

未完待续

发布了40 篇原创文章 · 获赞 13 · 访问量 838

猜你喜欢

转载自blog.csdn.net/weixin_43891021/article/details/99653032