码迷,mamicode.com
首页 > 其他好文 > 详细

五一 DAY 4

时间:2019-05-02 10:00:23      阅读:130      评论:0      收藏:0      [点我收藏+]

标签:mod   for   取值   cal   alt   hellip   span   回文串   十进制   

DAY 4

PART 1    进制转化

10 = 23+21= 1010(2)

      = 32+30= 101(3)

 

进制转化常见问题

1.十进制数 x ---->  k进制

2.k 进制数 x ---->  十进制

 

1.十进制数 x ---->  k进制

   短除法:

     x不断除以k ,直到得到商为零,过程中所得余数从下到上写,表示结果

技术图片

 

2.k 进制数 x ---->  十进制

    xn xn-1 xn-2 …… x1 x0 (k)

=  xn *kn + xn -1*kn-1 +……+ x0 *k0 (10)

 

 

特殊进制

二进制            01001=9

八进制

十进制

十六进制        0x1001=163+160=409

 

十六进制

每一位取值范围  0    1    2    3    4    5    6    7    8    9    A    B    C    D    E    F

                                                                                      (10)(11)(12)(13)(14)(15)

                           0x3F3F3F3F = 3*167+15*166+3*165+…… ≈1.1*109

 

 

PART 2 高精度

 

 

技术图片

 

 1.素数与筛法

2.exgcd

3.mod 运算与乘法逆元

 

 

 

 

 

~~~~下午考了个试,疯狂爆零~~~~ 

技术图片

技术图片

 

 PS:

如果一棵二叉树的结点要么是叶子结点,要么它有两个子结点,这样的树就是满二叉树。

 

若设二叉树的深度为h,除第 h 层外,其它各层 (1~h-1) 的结点数都达到最大个数,第 h 层所有的结点都连续集中在最左边,这就是完全二叉树。

 

等比数列通项公式、求和公式

技术图片

技术图片

 

 

then,看题

 

x的祖先是 a ,a可以有很多,从x到1路径上的所有点都是它的祖先

技术图片

对于两个点x,y,位置不同,向上跳到父节点,直到相遇,第一个相遇的点就是lca

 

题目计算的是任意两个点 LCA 的深度,这个数量等于,任意两个点公共的祖先共有多少个。

显然成立

技术图片

 

 任意两个点x,y的公共祖先是a的话,等价于x,y都在a的子树里,也就是相当于a是点对(x,y)的公共祖先,全部寻找完之后,会发现还有其他的点对的公共祖先是a,也就是a还是其他点对的公共祖先,问题就转化为枚举每个节点a,看它是多少个点对的公共祖先

 

比如我们枚举x,y,有多少个公共祖先a

 技术图片

换一下枚举顺序就是

技术图片

 

注意到没有必要将所有点对的 LCA 都计算出来,因为对于同一层的两个节点lca是相同的,每一层只需要算一个节点就行

 

 考虑计算第 i 层的某个节点,是多少个点对的公共祖先,这个数量就是该节点子树内节点数的平方。

技术图片

技术图片(等比数列求和)

 

技术图片

技术图片是每个a的点对的个数,技术图片是第i层有多少个点

 

技术图片

 

 

#include <bits/stdc++.h>

using namespace std;

const int mod = 998244353;
typedef long long LL;
int fpm(int p, int k)
{
    int res = 1;
    for (p %= mod; k; k >>= 1, p = (LL) p * p % mod)
        if (k & 1) res = (LL) res * p % mod;
    return res;
}
int main()
{
//    freopen("lca.in", "r", stdin);
//    freopen("lca.out", "w", stdout);
    int n, K; cin >> n >> K;
    int e = fpm(K - 1, mod - 2); //(K - 1) ^ (-1)
    int x = (fpm(K, n) - 1) * (LL) e % mod; //(K ^ n - 1) / (K - 1)
    int ans = (fpm(K, n + 1) + 1) * (LL) x % mod;
    ans = (ans - 2 * n * (LL) fpm(K, n)) % mod;
    ans = ans * (LL) e % mod * (LL) e % mod;
    cout << (ans < 0 ? ans + mod : ans);
}

 

 

技术图片

技术图片

 

 技术图片

 

 两个序列比较:

技术图片

四个就是多了两维

技术图片

 

 

 技术图片

t 中不同的回文子序列最多只有 2 m 个。(选或者不选)

问题转化为:怎么判断一个回文串 q 是不是 s 的子序列。

构造自动机:记 next[i][c] 表示 s[i + 1..n] 中 c 第一次最早出现的下标。

只需要沿着 next 走,就 能判断 s 是否包含 q 这个子序列。

理论时间复杂度 O(m2m + 26n),实际远远达不到这个复杂度

 

技术图片

技术图片

 

构造自动机:

 技术图片

#include <bits/stdc++.h>

using namespace std;
typedef long long LL;
const int maxn = 100005;

int n, m, nex[maxn][26], ans;
char a[maxn], b[maxn], c[maxn];

bool pal(int l)
{
    for (int i = 1, j = l; i < j ; i++, j--)
        if (c[i] != c[j]) return false;
    return true;
}
void solve(int stp, int l, int cur)
{
    if (l + m - stp + 1 <= ans) return ;
    if (stp > m) {if (pal(l)) ans = l; return ;}
    solve(stp + 1, l, cur);
    if (int t = nex[cur][b[stp] - a])
        c[l + 1] = b[stp], solve(stp + 1, l + 1, t);
}
int main()
{
//    freopen("lcscl.in", "r", stdin);
//    freopen("lcscl.out", "w", stdout);
    scanf("%s", a + 1); n = strlen(a + 1);
    scanf("%s", b + 1); m = strlen(b + 1);
    for (int i = n - 1; i >= 0; i--)
    {
        for (int j = 0; j < 26 ; j++)
            nex[i][j] = nex[i + 1][j];
        nex[i][a[i + 1] - a] = i + 1;
    }
    solve(1, 0, 0); printf("%d", ans);
    return 0;
}

 

 

 

 

 

技术图片

 技术图片

技术图片

当a,b > 100

a+5 , b-13更优

a,b,>0  b>=13

a+5 , b-13更优

b=7就不一定, 因为考虑到绝对值

复杂度O(30 n)

 

#include <bits/stdc++.h>

using namespace std;

typedef long long LL;
const int maxn = 100005;
const LL inf = 1ll << 50;
int n; LL a[maxn], b[maxn], now = 0, ans = 0;

LL xabs(LL x) {return x < 0 ? -x : x;}
LL calc(LL t) {
    LL res = inf;
    for (LL a = -4; a <= 4; a++)
        if ((t - a * 13) % 5 == 0) res = min(res, xabs(a) + xabs((t - a * 13) / 5));
    for (LL b = -12; b <= 12; b++)
        if ((t - b * 5) % 13 == 0) res = min(res, xabs(b) + xabs((t - b * 5) / 13));
    return res;
}
int main()
{
//    freopen("cards.in", "r", stdin);
//    freopen("cards.out", "w", stdout);
    scanf("%d", &n);
    for (int i = 1; i <= n; i++) scanf("%lld", &a[i]);
    for (int i = 1; i <= n; i++) scanf("%lld", &b[i]);
    for (int i = 1; i <= n; i++)
        now += a[i] - b[i], ans += calc(now);
    printf("%lld", ans);
}

 

五一 DAY 4

标签:mod   for   取值   cal   alt   hellip   span   回文串   十进制   

原文地址:https://www.cnblogs.com/xiaoyezi-wink/p/10799597.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!