8.13 2020 Multi-University Training Contest 8题解及补题

8.13 2020 Multi-University Training Contest 8题解及补题

比赛过程

题解

A

题意

解法

代码

//将内容替换成代码

B

题意

解法

代码

//将内容替换成代码

C Clockwise or Counterclockwise

题意

给出三个点的坐标,要求判断这三个点组成的圆是顺时针还是逆时针

解法

可以选第一个点和第二点组成一条直线,然后判断第三个点和该直线的关系即可。

代码

#include<bits/stdc++.h>
using namespace std; 
typedef long long ll;
const double eps = 1e-8;
const double PI = 3.14159265358979323846264338f;
inline int sgn(const double &x) {
    return x < -eps ? -1 : x > eps;
}

struct Point {
    double x, y;
    Point(double x = 0, double y = 0) : x(x), y(y) {}
    void input() {
        scanf("%lf%lf", &x, &y);
    }
    bool operator<(const Point &p) const {
        return sgn(x - p.x) < 0 || (!sgn(x - p.x) && sgn(y - p.y) < 0);
    }
    bool operator==(const Point &p) const {
        return !sgn(x - p.x) && !sgn(y - p.y);
    }
    Point operator+(const Point &p) const {
        return Point(x + p.x, y + p.y);
    }
    Point operator-(const Point &p) const {
        return Point(x - p.x, y - p.y);
    }
    Point operator*(const double c) const {
        return Point(x * c, y * c);
    }
    friend Point operator*(double c, const Point &p) {
        return p * c;
    }
    Point operator/(double c) {
        return Point(x / c, y / c);
    }
    double operator^(const Point &p) const { //揧YН揨b&Vz暲垮害
        return x * p.y - y * p.x;
    }
    double operator%(const Point &p) const { //�圭Н
        return x * p.x + y * p.y;
    }
    double norm() {
        return sqrt(x * x + y * y);
    }
    double arg() { //杩e縨寮у害 锛?pi,pi拞?
        return atan2(y, x);
    }
    friend Point rotate(const Point &v, double A) {
        Point p = Point(sin(A), cos(A));
        return Point(v ^ p, v % p);
    }
    friend Point rotate_around_point(const Point &v, const Point &p, double A) {
        return rotate(v - p, A) + p;
    }
};
struct Line {
    Point s, t;
    Line(Point s = Point(), Point t = Point()) : s(s), t(t) {}
    Point v() {
        return t - s;
    }
    double norm() {
        return v().norm();
    }
    //�逛{�)寸嚎涔[.h�(R隨珑�?online(0),暙U豬暯?1),椤烘i暯?-1)
    int relation(Point &p) {
        return sgn((v() ^ (p - s)));
    }
    bool point_on_line(Point &p) { //�规i鴵Z兀nj�)寸嚎涓?宸查sY)
        return sgn(v() ^ (p - s)) == 0;
    }
    bool point_on_seg(Point &p) {                               //�规i鴵Z兀nj绾挎釋涓?
        return point_on_line(p) && sgn((p - s) % (p - t)) <= 0; //揤Tm`如Pc
        // return point_on_line(p) && sgn((p - s) % (p - t)) < 0;//涓]匸負Z啶鄉�?
    }
    double dis_point_line(Point &p) { //�瑰W虜)寸嚎�(R顉涚�?
        return fabs((v() ^ (p - s)) / norm());
    }
    double dis_point_seg(Point &p) { //�瑰W嚏嚎驷寯(R顉涚�?
        if (sgn((p - s) % (t - s)) < 0) return (p - s).norm();
        if (sgn((p - t) % (s - t)) < 0) return (p - t).norm();
        return dis_point_line(p);
    }
    // 揜ゆg� a, b 撃�`翐fㄧm?绾跨k憮Z\|晶摯h, 琓m`摀枚錸j�)寸嚎涓?
    bool same_side(Point &a, Point &b) {
        return relation(a) == relation(b);
    }
    Point pedal(Point &p) { //�瑰犷�)寸嚎�(R雙-瓒?
        return s + (p - s) % v() / (v() % v()) * v();
    }
    Point sym_point(Point &p) { //�?p 揙充|,�)寸嚎�(R脶铉О鏟c
        return 2.0 * pedal(p) - p;
    }

    friend bool isParallel(Line &a, Line &b) { //揜ゆg卿袱鏼?绾挎i鴵Z兀钩琛\媫揤TnZ頃瞉卄庯�?
        return !sgn(a.v() ^ b.v());
    }
    friend bool is_Line_seg_intersection(Line &a, Line &b) { //绾?a)揬\€嚎娈?b)撃�`翑)镐氦锛X[負丰鄉�癸}(宸查sY)
        return a.relation(b.s) * a.relation(b.t) <= 0;
    }
    //揜╃ed�)镐技涓Y鏦褰㈠犷搴e繵〝pTnW氭痚緘彐盤櫢)寸嚎�(R旰?/揙XW綋箩_i鴵Z兀钩琛\媫涓]吂宠€k憮疶mU寭P]唚0浜ょPc(宸查sY)
    friend Point line_intersection(Line &a, Line &b) {
        double s1 = (a.s - b.s) ^ b.v();
        double s2 = (a.t - b.s) ^ b.v();
        return (a.t * s1 - a.s * s2) / (s1 - s2);
    }

    // 瑙R頪謹)镐氦, 涓ょ嚎娈典|帗萗    z翡膏Hoj绔�Pc澶R韐戜氦鏟c
    // 揜ゆg晴嚎驷寯)镐氦, 骞舵w0绾挎釋浜ょPc, 1瑙R頪謹)镐氦, 2�)镐氦, 0涓]労�
    friend int seg_intersection(Line &a, Line &b, Point &p) {
        int d1, d2, d3, d4;
        double s1, s2, s3, s4;
        d1 = sgn(s1 = a.v() ^ (b.s - a.s));
        d2 = sgn(s2 = a.v() ^ (b.t - a.s));
        d3 = sgn(s3 = b.v() ^ (a.s - b.s));
        d4 = sgn(s4 = b.v() ^ (a.t - b.s));

        //瑙R頪謹)镐氦
        if (d1 * d2 < 0 && d3 * d4 < 0) {
            p = (b.s * s2 - b.t * s1) / (s2 - s1);
            return 1;
        }

        //暼p剁I攟Q猰I浜?
        if (a.point_on_seg(b.s) || a.point_on_seg(b.t) || b.point_on_seg(a.s) || b.point_on_seg(b.s)) {
            return 2;
        }
        return 0;
    }

    //绾挎釋涔[.h�(R靚6�-醓z涚�?
    friend double dis_seg_seg(Line &a, Line &b) {
        double d1, d2, d3, d4;
        Point p;
        if (seg_intersection(a, b, p))
            return 0;
        else {
            d1 = a.dis_point_seg(b.s);
            d2 = a.dis_point_seg(b.t);
            d3 = b.dis_point_seg(a.s);
            d4 = b.dis_point_seg(a.t);
            return min(min(d1, d2), min(d3, d4));
        }
    }
};
int main(){
    int t;
    scanf("%d",&t);
    while(t--){
        Point a,b,c;
        cin>>a.x>>a.y>>b.x>>b.y>>c.x>>c.y;
        Line l;
        l.s=a;l.t=c;
        if(l.relation(b)==1){
            cout<<"Clockwise"<<endl;
        }
        else{
            cout<<"Counterclockwise"<<endl;
        }
    }
}

D Discovery of Cycles

题意

给定n个点m条边的无向图,边的编号为1到m,现在有q次在线询问,每次询问给出l,r(1<=l<=r<=m),

问编号在[l,r]内的边组成的图中是否存在环。

解法

因为3e5个询问,所以可以预处理出以每一个边为起点边形成环需要到达的最早的边

而判环比较简单的是并查集,但是不能每一个起点都重新跑一遍并查集,在起点边编号递增的情况下,

对应的答案编号肯定也是非递减的;所以可以选择删边,且能提供类似并查集判环的数据结构,可以使用LCT

代码

#include<bits/stdc++.h>
#define lc c[x][0]
#define rc c[x][1]
using namespace std;
const int N=3e5+10;
const int M=3e5+10;
int f[N],c[N][2];
int st[N];
bool tag[N];
int R[N];
struct edge{
    int from,to;
}e[M];
void init(){
    memset(f,0,sizeof(f));
    memset(c,0,sizeof(c));
    memset(tag,0,sizeof(tag));
}
inline bool nroot(int x){
    return c[f[x]][0]==x||c[f[x]][1]==x;
}
inline void pushr(int x){
    int t=lc;
    lc=rc,rc=t;
    tag[x]^=1;
}
inline void pushdown(int x){
    if(tag[x]){
        if(lc) pushr(lc);
        if(rc) pushr(rc);
        tag[x]=0;
    }
}
void rotate(int x){
    int y=f[x],z=f[y],k=c[y][1]==x,w=c[x][!k];
    if(nroot(y))c[z][c[z][1]==y]=x;c[x][!k]=y;c[y][k]=w;
    if(w)f[w]=y;f[y]=x;f[x]=z;
}
void splay(int x){
    int y=x,z=0;
    st[++z]=y;
    while(nroot(y)) st[++z]=y=f[y];
    while(z) pushdown(st[z--]);
    while(nroot(x)){
        y=f[x];z=f[y];
        if(nroot(y))
            rotate((c[y][0]==x)^(c[z][0]==y)?x:y);
        rotate(x);
    }
}
void access(int x){
    for(int y=0;x;x=f[y=x])
        splay(x),rc=y;
}
void makeroot(int x){
    access(x);splay(x);
    pushr(x);
}
int findroot(int x){
    access(x);splay(x);
    while(lc)pushdown(x),x=lc;
    splay(x);
    return x;
}
void split(int x,int y){
    makeroot(x);
    access(y);splay(y);
}
inline void link(int x,int y){
    f[x]=y;
}
void cut(int x,int y){
    makeroot(x);
    if(findroot(y)==x&&f[y]==x&&!c[y][0]){
        f[y]=c[x][1]=0;
    }
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--){
        init();
        int n,m,q;
        scanf("%d%d%d",&n,&m,&q);
        for(int i=1;i<=m;i++){
            scanf("%d%d",&e[i].from,&e[i].to);
        }
        int l=1,r=1;
        while(l<=m){
            while(r<=m){
                int u=e[r].from,v=e[r].to;
                makeroot(u);
                if(findroot(v)==u){
                    break;
                }
                link(u,v);
                r++;
            }
            if(r==m+1){
                for(int i=l;i<=m;i++)
                    R[i]=m+1;
                break;
            }
            R[l]=r;
            cut(e[l].from,e[l].to);
            l++;
        }
        int ans=0;
        while(q--){
            int x,y;
            scanf("%d%d",&x,&y);
            int k1=(x^ans)%m+1;
            int k2=(y^ans)%m+1;
            x=min(k1,k2);
            y=max(k1,k2);
            if(y>=R[x]){
                ans=1;
                printf("Yes\n");
            }
            else{
                ans=0;
                printf("No\n");
            }
        }
    }
    return 0;
}

E

题意

解法

代码

//将内容替换成代码

F Fluctuation Limit

题意

给你一个n和k,给你n个价格范围l,r,问最后没组价格的上下浮动能不能不超过k。若可以,那么输出YES并输出他的价格序列;否则出NO。

解法

我们可以根据给定的第一个区间,推断第二个区间满足第二个条件的范围,也就是[l1 - x, r1 + x],然后再让这个区间和[l2,r2]区间取并集,那么得到的区间中的任何一个数字都是合法区间

代码

#pragma region
#include <algorithm>
#include <cmath>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <unordered_map>
#include <vector>
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define rep(i, a, n) for (int i = a; i <= n; ++i)
#define per(i, a, n) for (int i = n; i >= a; --i)
namespace fastIO {
#define BUF_SIZE 100000
#define OUT_SIZE 100000
//fread->R
bool IOerror = 0;
//inline char nc(){char ch=getchar();if(ch==-1)IOerror=1;return ch;}
inline char nc() {
    static char buf[BUF_SIZE], *p1 = buf + BUF_SIZE, *pend = buf + BUF_SIZE;
    if (p1 == pend) {
        p1 = buf;
        pend = buf + fread(buf, 1, BUF_SIZE, stdin);
        if (pend == p1) {
            IOerror = 1;
            return -1;
        }
    }
    return *p1++;
}
inline bool blank(char ch) { return ch == ' ' || ch == '\n' || ch == '\r' || ch == '\t'; }
template <class T>
inline bool R(T &x) {
    bool sign = 0;
    char ch = nc();
    x = 0;
    for (; blank(ch); ch = nc())
        ;
    if (IOerror) return false;
    if (ch == '-') sign = 1, ch = nc();
    for (; ch >= '0' && ch <= '9'; ch = nc()) x = x * 10 + ch - '0';
    if (sign) x = -x;
    return true;
}
inline bool R(double &x) {
    bool sign = 0;
    char ch = nc();
    x = 0;
    for (; blank(ch); ch = nc())
        ;
    if (IOerror) return false;
    if (ch == '-') sign = 1, ch = nc();
    for (; ch >= '0' && ch <= '9'; ch = nc()) x = x * 10 + ch - '0';
    if (ch == '.') {
        double tmp = 1;
        ch = nc();
        for (; ch >= '0' && ch <= '9'; ch = nc())
            tmp /= 10.0, x += tmp * (ch - '0');
    }
    if (sign)
        x = -x;
    return true;
}
inline bool R(char *s) {
    char ch = nc();
    for (; blank(ch); ch = nc())
        ;
    if (IOerror)
        return false;
    for (; !blank(ch) && !IOerror; ch = nc())
        *s++ = ch;
    *s = 0;
    return true;
}
inline bool R(char &c) {
    c = nc();
    if (IOerror) {
        c = -1;
        return false;
    }
    return true;
}
template <class T, class... U>
bool R(T &h, U &... t) { return R(h) && R(t...); }
#undef OUT_SIZE
#undef BUF_SIZE
};  // namespace fastIO
using namespace fastIO;
template <class T>
void _W(const T &x) { cout << x; }
void _W(const int &x) { printf("%d", x); }
void _W(const int64_t &x) { printf("%lld", x); }
void _W(const double &x) { printf("%.16f", x); }
void _W(const char &x) { putchar(x); }
void _W(const char *x) { printf("%s", x); }
template <class T, class U>
void _W(const pair<T, U> &x) { _W(x.F), putchar(' '), _W(x.S); }
template <class T>
void _W(const vector<T> &x) {
    for (auto i = x.begin(); i != x.end(); _W(*i++))
        if (i != x.cbegin()) putchar(' ');
}
void W() {}
template <class T, class... U>
void W(const T &head, const U &... tail) { _W(head), putchar(sizeof...(tail) ? ' ' : '\n'), W(tail...); }
#pragma endregion
const ll maxn = 1e5 + 500;
const int mod=1e9+7;
ll gcd(ll T, ll b) { return b == 0 ? T : gcd(b, T % b); }
ll lcm(ll T, ll b) { return T / gcd(T, b) * b; }
ll mul(ll a,ll b, ll c) {
    ll ans = 0;
    while(b) {
        if(b&1) {
            ans= (ans+a)%c;
            b--;
        }
        b>>=1;
        a=(a+a)%c;
    }
    return ans;
}
ll powmod(ll a,ll b,ll c) {
    ll ans = 1;
    while(b) {
        if(b&1) {
            ans = mul(ans,a,c);
            b--;
        }
        b>>=1;
        a=mul(a,a,c);
    }
    return ans ;
}
struct node {
    ll l, r;
} a[maxn];
int main() {
    ll T;
    // cin>>T;
    scanf("%lld", &T);
    while (T--) {
        ll n, k;
        // cin>>n>>k;
        scanf("%lld%lld", &n, &k);
        for (int i=1; i<=n; ++i) {
            // cin>>a[i].l>>a[i].r;
            scanf("%lld%lld", &a[i].l, &a[i].r);
        }
        bool flag=true;
        for (int i=2; i<=n; ++i) {
            ll l0 = a[i-1].l-k;
            ll r0 = a[i-1].r+k;
            a[i].l = max(l0, a[i].l);
            a[i].r = min(r0, a[i].r);
            if (a[i].l > a[i].r) {
                flag=false;
                break;
            }
        }
        for (int i=n-1; i>=1; --i) {
            ll l0 = a[i+1].l-k;
            ll r0 = a[i+1].r+k;
            a[i].l = max(l0, a[i].l);
            a[i].r = min(r0, a[i].r);
            if (a[i].l > a[i].r) {
                flag=false;
                break;
            }
        }
        if (!flag) {
            // cout<<"NO\n";
            printf("NO\n");
        } else {
            // cout<<"YES\n";
            printf("YES\n");
            for (int i=1; i<=n; ++i) {
                if(i!=n) {
                    // cout<<a[i].l<<" ";
                    printf("%lld ", a[i].l);
                }
                else {
                    // cout<<a[i].l<<"\n";
                    printf("%lld\n", a[i].l);
                }
            }
        }
    }
    return 0;
}

G

题意

解法

代码

//将内容替换成代码

H Hexagon

题意

给出半径为n的六边形(由半径为1的小六边形组成),从某一个小六边形出发由六个方向,找到一条转向次数最多的路径(用方向表示)遍历所有的六边形(一个六边形只访问一次)。

解法

分别分成奇数和偶数的情况,然后奇数内三层都是一样的,特殊处理一下六边形出来的第一个边,还有六边形的最后一条边;偶数的内两层都是一样的,然后特殊处理一下六边形的最后一条边。每次加2层是加4步。

代码

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int INF=0x3f3f3f3f;
const double pi=acos(-1.0),eps=1e-8;
const ll mod =  998244353;
const int maxn=1e5+5;
struct node
{
    double x,y;
} cir[5],p1,p2;
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        int n;
        scanf("%d",&n);
        if(n%2==0)
        {
            printf("461234");
            if(n>2)
            {
                int num=5;
                int xx=2;
                while(xx<n)
                {
                    printf("34");
                    int x=6,y=4;
                    for(int k=0; k<6; k++)
                    {
                        if(k<5)
                        {

                            for(int i=0; i<num; i++)
                            {
                                if(i%2==0)
                                    printf("%d",x);
                                else
                                    printf("%d",y);
                            }
                        }
                        else
                        {
                            for(int i=0; i<num-3; i++)
                            {
                                if(i%2==0)
                                    printf("%d",x);
                                else
                                    printf("%d",y);
                            }
                        }
                        x=(x)%6+1;
                        y=(y)%6+1;
                    }
                    printf("4");
                    num+=4;
                    xx+=2;
                }
            }
        }
        else
        {
            printf("546126231342453564");
            if(n>3)
            {
                int num=7;
                n-=2;
                while(n>1)
                {
                    printf("546");

                    int x=1,y=5;
                    for(int i=0; i<num-2; i++)
                    {
                        if(i%2==0)
                            printf("%d",x);
                        else
                            printf("%d",y);
                    }
                    x=(x)%6+1;
                    y=(y)%6+1;
                    for(int k=0; k<4; k++)
                    {
                        for(int i=0; i<num; i++)
                        {
                            if(i%2==0)
                                printf("%d",x);
                            else
                                printf("%d",y);
                        }
                        x=(x)%6+1;
                        y=(y)%6+1;
                    }
                    for(int i=0; i<num-1; i++)
                    {
                        if(i%2==0)
                            printf("%d",x);
                        else
                            printf("%d",y);
                    }
                n-=2;
                num+=4;
                }

            }
        }
        printf("\n");
    }

    return 0;
}

I Isomorphic Strings

题意

给一个长度为n的字符串,问能不能分解成k个字段,每个字段长度相同,而且字符串的最小表示相同。其中k要大于1。

输出yes和no

解法

要想成功分解成k段,那么最少每段的字符数量要相同,而且还要被n整除,所以找到所有字符和n的公约数len,n/len就是最小的k,

k每次可以增长一倍,然后判断能不能被n整除,然后判断每个字符串的不同种类就可以用map记录每一个的hash就行。

最后判断每一段的字符串hash值,在不在这些map已经记录的hash值中。

代码

#include<bits/stdc++.h>
#define emplace_back push_back
#define pb push_back
using namespace std;
typedef long long LL;
const LL mod = 13331;
const double eps = 1e-6;
const LL inf = 0x3f3f3f3f;
const LL N = 5e6 + 10;
LL num[30];
LL ha[N];
LL p[N];
char s[N];
map<LL, LL> mp;
int main()
{
    p[0] = 1;
    for (LL i = 1; i < N; i++)
    {
        p[i] = p[i - 1] * mod;
    }
    LL t;
    scanf("%lld", &t);
    while (t--)
    {
        LL n;
        scanf("%lld", &n);
        scanf("%s", s + 1);
        memset(num, 0, sizeof(num));
        ha[0] = 0;
        for (LL i = 1; i <= n; i++)
        {
            num[s[i] - 'a' + 1]++;
            ha[i] = ha[i - 1] * mod + (s[i] - 'a' + 1);
        }
        LL gg = n;
        for (LL i = 1; i <= 26; i++)
        {
            if (num[i])
                gg = __gcd(gg, num[i]);
        }
        LL u = n / gg;
        LL flog = 1;
        if (u == 1 && n != 1)
        {
            flog = 0;
        }
        else
        {
            for (LL i = 1; i < gg; i++)
            {
                LL len = i * u;
                if(n%len)
                {
                    continue;
                }
                flog = 0;
                mp.clear();
                LL k = ha[len] - ha[0] * p[len];
                mp[k] = 1;
                for (LL j = 1; j < len; j++)
                {
                    k = k * mod + (s[j]-96);
                    mp[k - ha[j] * p[len]] = 1;
                }
                for (LL j = 1; j * len <= n; j++)
                {

                    if (mp[ha[j * len] - ha[(j - 1) * len] * p[len]] == 0)
                    {
                        flog = 1;
                        break;
                    }
                }
                if (flog == 0)
                {

                    break;
                }
            }
        }
        if (flog == 0)
        {
            printf("Yes\n");
        }
        else
        {
            printf("No\n");
        }
    }
    return 0;
}

J

题意

解法

代码

//将内容替换成代码

K Kidnapper's Matching Problem

题意

给出两个数组A,B和集合S,分别有n,m,k个数

求题目中表达式 题目链接

解法

先求出S集合的线性基,然后对A,B集合中的数,消去对应线性基中的位。

则剩下的数如果想满足异或后在S集合中,必须相等。因为余下的位已经无法用线性基表示。

然后就变成了找A串中的B串,用KMP处理

代码

#include <bits/stdc++.h>
using namespace std;
int const maxn=2e5+7,mod=1e9+7;
const int MAXL = 29,maxn2=5e4+7;
int n,m,k,nex[maxn2];
bool res[maxn];
long long a[maxn],b[maxn2],s[maxn2];
struct LinearBasis{
    long long aa[MAXL+1];
    LinearBasis(){
        std::fill(aa, aa + MAXL + 1, 0);
    }

    void insert(long long t){
        for (int j = MAXL; j >= 0; j--){
            if (!(t & (1ll << j))) continue;
            if (aa[j]) t ^= aa[j];
            else
            {
                for (int k = 0; k < j; k++) if (t & (1ll << k)) t ^= aa[k];
                for (int k = j + 1; k <= MAXL; k++) if (aa[k] & (1ll << j)) aa[k] ^= t;
                aa[j] = t;
                return;
            }
        }
    }

    void build(long long *x, int len){
        std::fill(aa, aa + MAXL + 1, 0);
        for (int i = 1; i <= len; i++){
            insert(x[i]);
        }
    }
}ji;//线性基模板
int main(){
    int t;
    scanf("%d",&t);

    for(int q=1;q<=t;q++){
        scanf("%d%d%d",&n,&m,&k);
        for(int i=1;i<=n;i++){
            scanf("%lld",&a[i]);
        }
        for(int i=1;i<=m;i++){
            scanf("%lld",&b[i]);
        }
        for(int i=1;i<=k;i++){
            scanf("%lld",&s[i]);
        }
        ji.build(s,k);
        for(int i=1;i<=n;i++){
            for(int j=MAXL;j>=0;j--)if(a[i]>>j&1)a[i]^=ji.aa[j];
        }
        for(int i=1;i<=m;i++){
            for(int j=MAXL;j>=0;j--)if(b[i]>>j&1)b[i]^=ji.aa[j];
        }
        long long ans=0;
        nex[1]=0;
        for(int i=2,j=0;i<=m;i++){
            while(j&&b[j+1]!=b[i])j=nex[j];
            if(b[j+1]==b[i])j++;
            nex[i]=j;
        }
        memset(res,0,n);
        for(int i=1,j=0;i<=n;i++){
            while(j&&b[j+1]!=a[i])j=nex[j];
            if(b[j+1]==a[i])j++;
            if(j==m){
                res[i-m]=1;
                j=nex[j];
            }
        }
        for(int i=n-m;i>=0;i--)ans=(ans*2+res[i])%mod;
        printf("%lld\n",ans);
    }
}

posted @ 2020-09-01 23:14  cugbacm03  阅读(230)  评论(0)    收藏  举报