2017.10.6 QBXT 模拟赛

题目链接

T1

 Sort 一下与原数组比较 ,若有两个数或者没有数发生位置交换 ,则输出YES ,否则输出NO

#include <algorithm>
#include <cctype>
#include <cstdio>
#define N 1005000
int n, cnt1, cnt2, sum;
struct node
{
    int num, pos;
    bool operator < (node a)const
    {
        if (num != a.num) return num < a.num;
        else return pos < a.pos;
    }
}a[N];
int main(int argc, char *argv[])
{
    freopen("sort.in", "r", stdin); freopen("sort.out", "w", stdout);
    scanf("%d", &n);
    for (int i = 1; i <= n; ++i) scanf("%d", &a[i].num), a[i].pos=i;
    std :: sort(a + 1, a + n + 1);
    for (int i = 1; i <= n; ++i)
    {
        if (a[i].pos > i) cnt1++;
        if (a[i].pos < i) cnt2++;
    }
    if (cnt1 == 1 || cnt2 == 1 || (!cnt2 && !cnt1)) puts("YES");
    else puts("NO");
    return 0;
    fclose(stdin); fclose(stdout);
}
View Code

T2

  

    同余方程组

  前60%的数据可以用中国剩余定理

  后面的数据 用数学构造

   X%a1=b1

   X%a2=b2

   ....

   X+k1a1=b1

   X+k2a2=b2 

  相减得到 k1a1-k2a2=b1-b2

  解这个方程,用exgcd(a1,-a2,k1,k2)

    Ax+by=gcd(a,b)

    Ax+by=c;

  把k1k2回带到原式中,求出x

   X0=b1-k1a1 

   X%a1a2=x0

#include<iostream>
#include<cstdio>
typedef long long LL; 
using namespace std;

LL n,m[5],a[5];
LL exgcd(LL a,LL b,LL &x,LL &y)
{
    if (b == 0)
    {
        x = 1, y = 0;
        return a;
    }
    LL r = exgcd(b, a % b, x, y);
    LL tmp = x;
    x = y;
    y = tmp - a / b * y;
    return r;
}
inline LL crt()
{
    LL a1 = a[1], a2, m2, d, c, m1=m[1];
    for (LL i = 2; i <= 4; ++i)
    {
        a2 = a[i], m2 = m[i];
        c = a2 - a1;
        LL x, y;
        d = exgcd(m1, m2, x, y);
        x = x * c / d;
        int mod = m2 / d;
        x = (mod + x % mod) % mod;
        a1 += m1 * x;
        m1 *= mod;
    }
    return a1;
}
int main(int argc,  char *argv[])
{
    freopen("mod.in", "r", stdin);
    freopen("mod.out", "w", stdout);
    for(int i = 1; i <= 4; i++) cin >> m[i] >> a[i];
    cout << crt() << endl;
    return 0;
    fclose(stdin); fclose(stdout);
}
View Code

T3

  可以发现回文串是可以二分的

 比如:bbbabcbaabcba 我们以第1c为中心,发现回文半径是3,大于3一定不是回文串。当回文串长度为偶数的时候,我们需要特殊处理一下。 

  现在有一个结论:本质不同的回文串个数只有O(N)

  本质不同:字符串本身是不同的。

  每一次处理完回文串,我们要把他的hash值记录下来。

#include <algorithm>
#include <cstring>
#include <cstdio>
#include <map>

using namespace std;
typedef unsigned long long ULL;
typedef long long LL;
char s[10005];
ULL h[10005], rh[10005], pw[10005];
int L;
ULL hs(int l, int r)
{
    return h[r] - h[l - 1] * pw[r - l + 1];
}
ULL rhs(int l, int r)
{
    return rh[l] - rh[r + 1] * pw[r - l + 1];
}
struct N
{
    int a[26];
    bool ok()
    {
        int b[26];
        for (int i = 0; i < 26; i++) b[i] = a[i];
        sort(b,b + 26);
        for (int i = 0; i < 25; i++)
        {
            if (b[i] > 0 && b[i] == b[i + 1]) return true;
        }
        return false;
    }
    void clear()
    {
        memset(a, 0, sizeof(a));
    }
};
LL ans = 0;
map<ULL, LL> num;
map<ULL, N> A;
void solve_odd()
{
    for (int i = 1; i <= L; i++)
    {
        int l = 1,r = min(i,L - i + 1) + 1;
        while (r - l > 1)
        {
            int mid = (l + r) >> 1;
            if (hs(i - mid + 1, i + mid - 1) == rhs(i - mid + 1, i + mid - 1)) l = mid;
            else r = mid;
        }
        int p = l;
        int tmp = p;
        while (tmp >= 1 && num.find(hs(i - tmp + 1, i + tmp - 1)) == num.end()) tmp--;
        LL sum = 0;
        N st;
        st.clear();
        if (tmp >= 1)
        {
            sum = num[hs(i - tmp + 1, i + tmp - 1)];
            st = A[hs(i - tmp + 1 ,i + tmp - 1)];
        }
        while (tmp < p)
        {
            st.a[s[i + tmp]-'a'] += (tmp == 0 ? 1 : 2);
            if (st.ok()) sum++;
            num[hs(i - tmp, i + tmp)] = sum;
            A[hs(i - tmp, i + tmp)] = st;
            tmp++;
        }
        ans += sum;  
    }
}
void solve_even()
{
    A.clear();
    num.clear();
    for(int i = 1; i < L; i++)
    {
        int l = 1,r = min(i,L - i) + 1;
        while (r - l > 1)
        {
            int mid = (l + r) >> 1;
            if (hs(i - mid + 1, i + mid) == rhs(i - mid + 1, i + mid)) l = mid;
            else r = mid;
        }
        int p = l,tmp = p;
        while (tmp >= 1 && num.find(hs(i - tmp + 1, i + tmp)) == num.end()) tmp--;
        LL sum = 0;
        N st;
        st.clear();
        if (tmp >= 1)
        {
            sum = num[hs(i - tmp + 1, i + tmp)];
            st = A[hs(i - tmp + 1, i + tmp)];
        }
        while (tmp < p)
        {
            st.a[s[i + tmp + 1] - 'a'] += 2;
            if (st.ok()) sum++;
            num[hs(i - tmp, i + tmp + 1)] = sum;
            A[hs(i - tmp, i + tmp + 1)] = st;
            tmp++;
        }
        ans += sum;
    }
}
int main()
{
    freopen("str.in", "r", stdin);
    freopen("str.out", "w", stdout);
    scanf("%s", s + 1);
    L = strlen(s + 1);
    s[0] = '#';
    pw[0] = 1;
    for(int i = 1; i <= L; i++) pw[i] = pw[i - 1] * 13131 ;
    for(int i = 1; i <= L; i++) h[i] = h[i - 1] * 13131 + s[i];
    for (int i = L; i >= 1; i--) rh[i] = rh[i + 1] * 13131 + s[i];
    solve_odd();
    solve_even();
    printf("%lld
", ans);
    fclose(stdout);
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/ruojisun/p/7646959.html