In mathematics you don't understand things, you just get used to them.

分类 笔记 下的文章

Description

Link.

求 $\sum_{i=1}^{n}\text{fibonacci}_{i}\times i^{k}=\sum_{i=1}^{n}(F_{i-1}+\text{fibonacci}_{i-2})\times i^{k}$,$1\le n\le10^{17},1\le k\le40$。

Solution

简记 $F_{i}=\text{fibonacci}_{i}$。首先我们作个差:

$$ ans_{n}=\sum_{i=1}^{n}F_{i}\times i^{k}=\sum_{i=1}^{n}(F_{i-1}+F_{i-2})\times i^{k} \\ ans_{n}-ans_{n-1}=F_{n}\times n^{k} \\ $$

然后:

$$ \begin{aligned} ans_{n}&=ans_{n-1}+F_{n}\times n^{k} \\ &=ans_{n-1}+F_{n-1}\times(n-1+1)^{k}+F_{n-2}\times(n-2+2)^{k} \\ &=ans_{n-1}+\left(\sum_{i=0}^{k}A_{i-1}(i)\times\binom{k}{i}\right)+\left(\sum_{i=0}^{k}A_{i-2}(i)\times\binom{k}{i}\times2^{k-i} \right) \end{aligned} $$

后面的 dirty work 实在不想做,口胡选手选择放弃。

Oops, something went wrong.

Description

Link.

Given is a rooted tree with the $\sf1$-th node as the root.

The tree will be given in this way: it will tell you that the parent of the $\sf i$-th node is $a_{i}$.

Supporting the following operations:

  • 1 l r x: let $\sf \forall i\in[l,r],a_{i}=max\{a_{i}-x,1\}$.
  • 2 u v: find the LCA (Lowest Common Ancestor) of $\sf u$ and $\sf v$.

Solution

考虑到修改操作是对结点进行的操作,然后这个东西不太能直接 LCT 或树剖,考虑照序列来分块,那么我们来对结点编号分块。

  1. 修改;

$\quad$维护一个属性 $\sf top_{u}$ 表示在原树上结点 $\sf u$ 的祖先中不和 $\sf u$ 在同一个块里面的编号最大的一个结点的编号,如果不存在的话就令 $\sf top_{u}=1$。这样的话你从结点 $\sf u$ 跳到 root 的复杂度为 $\sf O(\sqrt{n})$。接下来考虑怎么维护这个东西。

$\quad$散块我们直接暴力扫着改;对于整块,可以发现如果一个块的被修改次数超过了块的大小,那么就一定会有 $\sf top_{u}=fa_{u}$。

  1. 询问。

$\quad$分三个类讨论,这个比较好做(差不多和树剖找 LCA 一个样子)。

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
LL n,m,top[400010],deln[1000],tag[1000],belong[400010],bl[1000],br[1000],fa[400010],bs;
#define gtlf(x) ((x-1)*bs+1)
#define gtrg(x) (min(x*bs,n))
void updtop(LL x)
{
    if(belong[x]^belong[fa[x]])    top[x]=fa[x];
    else    top[x]=top[fa[x]];
}
void turndown(LL x)
{
    if(tag[x])
    {
        for(LL i=gtlf(x);i<=gtrg(x);++i)    fa[i]=max(fa[i]-tag[x],1ll);
        tag[x]=0;
    }
}
template<typename T>
void read(T &hhh)
{
    T x=0;
    char c=getchar();
    while(c<'0' || c>'9')    c=getchar();
    while(c>='0' && c<='9')    x=(x<<3)+(x<<1)+(c&15),c=getchar();
    hhh=x;
}
template<typename T>
void write(T x,char las='\n')
{
    static int st[100],top=0;
    do st[++top]=x%10,x/=10; while(x);
    while(top)    putchar(st[top]^'0'),--top;
    putchar(las);
}
int main()
{
    read(n),read(m),bs=sqrt(double(n))+1,fa[1]=belong[1]=1;
    for(LL i=2;i<=n;++i)    read(fa[i]);
    for(LL i=2;i<=n;++i)    belong[i]=(i-1)/bs+1,updtop(i);
    LL las=0;
    while(m--)
    {
        LL opt; read(opt);
        if(opt==1)
        {
            LL opl,opr,opx;
            read(opl),read(opr),read(opx);
            opl^=las,opr^=las,opx^=las;
            turndown(belong[opl]);
            if(belong[opl]==belong[opr])
            {
                turndown(belong[opl]);
                for(LL i=opl;i<=opr;++i)    fa[i]=max(fa[i]-opx,1ll),updtop(i);
                for(LL i=opr+1;i<=gtrg(belong[opl]);++i)    updtop(i);
            }
            else
            {
                turndown(belong[opl]);
                for(LL i=opl;i<=gtrg(belong[opl]);++i)    fa[i]=max(fa[i]-opx,1ll),updtop(i);
                for(LL i=gtlf(belong[opl]);i<opl;++i)    updtop(i);
                turndown(belong[opr]);
                for(LL i=gtlf(belong[opr]);i<=opr;++i)    fa[i]=max(fa[i]-opx,1ll),updtop(i);
                for(LL i=opr+1;i<=gtrg(belong[opr]);++i)    updtop(i);
                for(LL i=belong[opl]+1;i<belong[opr];++i)
                {
                    if(deln[i]>=bs)    tag[i]+=opx;
                    else
                    {
                        ++deln[i];
                        for(LL j=gtlf(i);j<=gtrg(i);++j)    fa[j]=max(fa[j]-opx,1ll),updtop(j);
                    }
                }
            }
        }
        else
        {
            LL opx,opy; read(opx),read(opy);
            opx^=las,opy^=las;
            while(opx^opy)
            {
                LL fopx,fopy;
                if(deln[belong[opx]] < bs) fopx=top[opx];
                else fopx = max(1LL , fa[opx] - tag[belong[opx]]);
                if(deln[belong[opy]] < bs) fopy=top[opy];
                else fopy = max(1LL , fa[opy] - tag[belong[opy]]);
                if(belong[opx]^belong[opy])
                {
                    if(belong[opx]>belong[opy])    opx=fopx;
                    else    opy=fopy;
                }
                else if(fopx^fopy)    opx=fopx,opy=fopy;
                else
                {
                    if(opx>opy)    turndown(belong[opx]),opx=max(1LL , fa[opx] - tag[belong[opx]]);
                    else    turndown(belong[opy]),opy=max(1LL , fa[opy] - tag[belong[opy]]);
                }
            }
            write(las=opx);
        }
    }
    return 0;
}

Description

Link.

  • 区间推平;
  • 区间数颜色。

Solution

考虑无修的情况,我们是采用维护每个数的 $pre$ 来做的。具体一点就是对于每一个 $a_{i}$ 维护 $pre_{i}=\max\{j\in[1,i),s.t.a_{j}=a_{i}\}$。然后数区间内 $pre$ 严格小于左端点的元素个数。

区间推平不好做,考虑削弱这一层修改,考虑单点修改怎么做。

修改一个 $a_{i}=x$,则受影响的下标有:

  • $j,s.t.pre_{j}=i$;
  • $i$;
  • $\min\{j\in(i,n],s.t.a_{j}=x\}$。

这个东西套个 std::map 能直接维护。

对于区间修改,有这样的结论:

对于所有修改,$pre$ 变化次数为 $\mathcal{O}(n+m)$。

做不来区间推平翻题解翻来的,至于证明不太会,摊还分析证复杂度没用过。

反正综上就能做了嘛,不知道为什么那么多人都喜欢写树套树,反正我是 CDQ。

//in the autumn sky
#include<bits/stdc++.h>
using namespace std;
#define fs first
#define sc second
struct oper
{
    int opt,opl,opr,opx;
    oper(int A=0,int B=0,int C=0,int D=0){opt=A,opl=B,opr=C,opx=D;}
};
struct ST_modify
{
    int ID,pos,pr,val;
    ST_modify(int A=0,int B=0,int C=0,int D=0){ID=A,pos=B,pr=C,val=D;}
    bool operator<(const ST_modify &ano)const{return pr<ano.pr;}
};
struct ST_query
{
    int ID,l,r;
    ST_query(int A=0,int B=0,int C=0){ID=A,l=B,r=C;}
    bool operator<(const ST_query &ano)const{return l<ano.l;}
};
vector<int> pri;
vector<ST_modify> mod;
vector<ST_query> que;
int pre[100010],n,m,tr[100010],curInd,ans[100010];
map<int,int> mapo[200010];
map<int,pair<int,int> > exmapo; // for ODT
#define lowbit(x) ((x)&(-(x)))
void ins(int pos,int delta)
{
    ++pos;
    while(pos<=n)
    {
        tr[pos-1]+=delta;
        pos+=lowbit(pos);
    }
}
int find(int pos)
{
    int res=0;
    while(pos)
    {
        res+=tr[pos-1];
        pos^=lowbit(pos);
    }
    return res;
}
void ODT_split(int pos)
{
    auto iter=exmapo.lower_bound(pos);
    int stan=n;
    if(iter!=exmapo.end())  stan=iter->fs;
    if(stan^pos)
    {
        --iter;
        exmapo.emplace(pos,iter->sc);
        auto exiter=mapo[iter->sc.sc].emplace(pos,iter->sc.fs).fs;
        iter->sc.fs=pos;
        prev(exiter)->sc=pos;
    }
}
void pushOp(int pos,int after,int ID)
{
    mod.emplace_back(ST_modify(ID,pos,pre[pos],-1));
    pre[pos]=after;
    mod.emplace_back(ST_modify(ID,pos,after,1));
}
void rawGrass(int onel,int oner,int anol,int anor,int parl,int parr)
{
    if(onel==oner || anol==anor)
    {
        sort(mod.begin()+onel,mod.begin()+oner);
        sort(que.begin()+anol,que.begin()+anor);
    }
    else
    {
        int mid=(parl+parr)>>1,exmid1=onel,exmid2=anol;
        while(exmid1<oner && mod[exmid1].ID<mid)    ++exmid1;
        while(exmid2<anor && que[exmid2].ID<mid)    ++exmid2;
        rawGrass(onel,exmid1,anol,exmid2,parl,mid);
        rawGrass(exmid1,oner,exmid2,anor,mid,parr);
        int ex=onel;
        for(int i=exmid2;i<anor;++i)
        {
            while(ex<exmid1 && mod[ex].pr<que[i].l)    ins(mod[ex].pos,mod[ex].val),++ex;
            ans[que[i].ID]+=find(que[i].r)-find(que[i].l);
        }
        for(int i=onel;i<ex;++i)    ins(mod[i].pos,-mod[i].val);
        inplace_merge(mod.begin()+onel,mod.begin()+exmid1,mod.begin()+oner);
        inplace_merge(que.begin()+anol,que.begin()+exmid2,que.begin()+anor);
    }
}
int main()
{
    scanf("%d %d",&n,&m);
    vector<int> a(n);
    vector<oper> b(m);
    for(int &i:a)   scanf("%d",&i),pri.emplace_back(i);
    for(oper &i:b)
    {
        scanf("%d %d %d",&i.opt,&i.opl,&i.opr);
        if(i.opt==1)    scanf("%d",&i.opx),pri.emplace_back(i.opx);
        --i.opl;
    }
    sort(pri.begin(),pri.end());
    pri.erase(unique(pri.begin(),pri.end()),pri.end());
    for(int &i:a)   i=lower_bound(pri.begin(),pri.end(),i)-pri.begin();
    for(oper &i:b)
    {
        if(i.opt==1)    i.opx=lower_bound(pri.begin(),pri.end(),i.opx)-pri.begin();
    }
    curInd=0;
    for(int i:a)
    {
        if(mapo[i].size()!=int(0))  pre[curInd]=prev(mapo[i].end())->fs;
        else    pre[curInd]=-1;
        mod.emplace_back(ST_modify(-1,curInd,pre[curInd],1));
        mapo[i].emplace(curInd,curInd+1);
        exmapo.emplace(curInd,make_pair(curInd+1,i));
        ++curInd;
    }
    curInd=0;
    for(oper i:b)
    {
        int ty=i.opt,l=i.opl,r=i.opr,x=i.opx;
        if(ty==1)
        {
            ODT_split(l),ODT_split(r);
            auto iter=mapo[x].lower_bound(l);
            auto ptr=exmapo.lower_bound(l);
            int rpe=(iter!=mapo[x].begin())?((iter=prev(iter))->sc-1):(-1); // for Suf
            while(ptr!=exmapo.end())
            {
                if(ptr->fs==r)  break;
                pushOp(ptr->fs,rpe,curInd);
                int tmp=ptr->sc.sc;
                auto exiter=mapo[tmp].erase(mapo[tmp].find(ptr->fs));
                if(exiter!=mapo[tmp].end())
                {
                    if(exiter==mapo[tmp].begin())   pushOp(exiter->fs,-1,curInd);
                    else    pushOp(exiter->fs,prev(exiter)->sc-1,curInd);
                }
                rpe=ptr->sc.fs-1;
                ptr=exmapo.erase(ptr);
            }
            iter=mapo[x].lower_bound(r);
            if(iter!=mapo[x].end()) pushOp(iter->fs,r-1,curInd);
            exmapo.emplace(l,make_pair(r,x));
            mapo[x].emplace(l,r);
        }
        else    que.emplace_back(ST_query(curInd,l,r));
        ++curInd;
    }
    rawGrass(0,int(mod.size()),0,int(que.size()),-1,m);
    curInd=0;
    for(oper i:b)
    {
        if(i.opt==2)    printf("%d\n",ans[curInd]);
        ++curInd;
    }
    return 0;
}

「ABC 197A」Rotate

Link.

略。

#include<bits/stdc++.h>
using namespace std;
int main(){
    char a,b,c;cin>>a>>b>>c;cout<<b<<c<<a;
    return 0;
}

「ABC 197B」Visibility

Link.

扫。

#include<bits/stdc++.h>
using namespace std;
int main(){
    int h,w,x,y;cin>>h>>w>>x>>y;vector<string> a(h);--x,--y;
    for(string &i:a)cin>>i;
    int ans=0;
    for(int i=x;~i;--i)if(a[i][y]=='.')++ans;/*,printf("(%d %d)\n",i+1,y+1);*/else break;
    for(int i=x;i<h;++i)if(a[i][y]=='.')++ans;/*,printf("(%d %d)\n",i+1,y+1);*/else break;
    for(int i=y;~i;--i)if(a[x][i]=='.')++ans;/*,printf("(%d %d)\n",x+1,i+1);*/else break;
    for(int i=y;i<w;++i)if(a[x][i]=='.')++ans;/*,printf("(%d %d)\n",x+1,i+1);*/else break;
    cout<<ans-3;
    return 0;
}

「ABC 197C」ORXOR

Link.

二进制枚举暴力算。

#include<bits/stdc++.h>
using namespace std;
long long n,a[30],b[30];
int main(){
    scanf("%lld",&n);for(long long i=1;i<=n;++i){scanf("%lld",&a[i]);}
    long long up=(1<<n),ans=1e18;
    for(long long i=0;i<=up;++i){
        long long ct=1;
        b[ct]=a[1];
        for(long long j=2;j<=n;++j)if(((i>>(j-1))&1)^((i>>(j-2))&1))b[++ct]=a[j];else b[ct]|=a[j];
        long long tmp=0;
        for(long long j=1;j<=ct;++j)tmp^=b[j];
        ans=min(ans,tmp);
    }
    printf("%lld\n",ans);
    return 0;
}

「ABC 197D」Opposite

Link.

数学题,不会,而且读不太懂题。

// Oops, something went wrong.

「ABC 197E」Traveler

Link.

这个题看起来就很 关路灯

对于每一种颜色(这里的颜色是指我们已经收集完了上一种颜色,正在收集的颜色),我们不可能走过而不拾。

于是收完一种颜色后,我们一定是这种颜色的的最左 / 右边。

然后就可以 DP 了;设 $f_{i,0\text{ or }1}$ 为拾 $i$-th 颜色,在左 / 右,转移显然。

/*
Denote f[i][0/1] for the minimum time, that we finish collecting the i-th color and we're at the left/right (0/1) endpoint.
f[i][0]=min( f[las][0]+Dist( R[las],L[i] ),f[las][1]+Dist( L[las],L[i] ) )+R[i]-L[i];
f[i][1]=min( f[las][0]+Dist( R[las],R[i] ),f[las][1]+Dist( L[las],R[i] ) )+R[i]-L[i];
*/
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const LL INF=1e18;
int n;
LL f[200010][2],L[200010],R[200010];
int main()
{
    scanf("%d",&n);
    for( int i=1;i<=n;++i )    L[i]=INF,R[i]=-INF;
    for( int i=1;i<=n;++i )
    {
        LL pos;
        int color;
        scanf( "%lld %d",&pos,&color );
        L[color]=min( pos,L[color] );
        R[color]=max( pos,R[color] );
    }
    #define Dist( x,y ) ( LL( abs( ( x )-( y ) ) ) )
    for( int i=1,las=0;i<=n+1;++i )
    {
        if( L[i]!=INF )
        {
            f[i][0]=min( f[las][0]+Dist( R[las],L[i] ),f[las][1]+Dist( L[las],L[i] ) )+R[i]-L[i];
            f[i][1]=min( f[las][0]+Dist( R[las],R[i] ),f[las][1]+Dist( L[las],R[i] ) )+R[i]-L[i];
            las=i;
        }
    }
    printf( "%lld\n",f[n+1][1] );
    return 0;
}

「ABC 197F」Construct a Palindrome

Link.

相当于是从 $1$ 和 $n$ 同时走,每次走字母一样的边,直接双向 BFS 即可。

#include<bits/stdc++.h>
using namespace std;
#define turn(c) ((c)-'a')
#define fs first
#define sc second
const int INF=1e9;
vector<int> suf[1010][26];
int n,m,ans=INF,vis[1010][1010];
struct node
{
    int fs,sc,val;
    node(int A=0,int B=0,int C=0){fs=A,sc=B,val=C;}
};
queue<node> q;
int main()
{
    // freopen("in.in","r",stdin);
    // freopen("my.out","w",stdout);
    scanf("%d %d",&n,&m);
    vis[1][n]=1;
    for(int i=1;i<=m;++i)
    {
        int x,y;
        scanf("%d %d",&x,&y);
        char c=getchar();
        while(c<'a' || c>'z')    c=getchar();
        suf[x][turn(c)].emplace_back(y);
        suf[y][turn(c)].emplace_back(x);
    }
    q.emplace(node(1,n,0));
    while(!q.empty())
    {
        int one=q.front().fs,ano=q.front().sc,lav=q.front().val;
        q.pop();
        if(lav==ans)    return printf("%d\n",ans<<1),0;
        for(int i=0;i<26;++i)
        {
            for(int exone:suf[one][i])
            {
                for(int exano:suf[ano][i])
                {
                    if(exone==ano || exano==one)    return printf("%d\n",lav<<1|1),0;
                    if(exone==exano)    ans=lav+1;
                    if(!vis[exone][exano])
                    {
                        vis[exone][exano]=1;
                        q.emplace(node(exone,exano,lav+1));
                    }
                }
            }
        }
    }
    printf("-1\n");
    return 0;
}

「ABC 196A」Difference Max

Link.

略。

#include<cstdio>
long long a,b,c,d;
int main(){
    scanf("%lld %lld %lld %lld",&a,&b,&c,&d);
    printf("%lld\n",b-c);
    return 0;
}

「ABC 196B」Round Down

Link.

略。

#include<cstdio>
#include<cstring>
char s[10000];
int main(){
    scanf("%s",s);int len=strlen(s);
    for(int i=0;i<len;++i)if(s[i]^'.')putchar(s[i]);else break;
    return 0;
}

「ABC 196C」Doubled

Link.

分类讨论即可,可能会有点点细节需要注意。

#include<cstdio>
#include<algorithm>
using namespace std;
long long n;
int dig[20],cnt;
long long qpow(long long bas,long long fur){long long res=0;for(long long i=1;i<=fur;++i)res=res*10+9;return res;}
long long getnum(int l,int r){long long res=0;for(int i=r;i>=l;--i)res=res*10+dig[i];return res;}
int main(){
    scanf("%lld",&n);long long bk=n;do dig[++cnt]=bk%10,bk/=10; while(bk);
    if(cnt==1)return puts("0"),0;int lm=(cnt>>1);
    long long pre=getnum(cnt-lm+1,cnt),suf=getnum(1,lm);
    if(cnt&1)printf("%lld\n",qpow(9,lm));
    else{
        if(pre<=suf)printf("%lld\n",pre);
        else printf("%lld\n",pre-1);
    }
    return 0;
}
/*
23333

3 3 3 3 2

232
*/

「ABC 196D」Hanjo

Link.

暴搜。

#include<iostream>
using namespace std;
int h,w,a,b,ans;
void dfs(int solvedNumber,int stateBoard,int leftLongerBlock,int leftCenterBlock)
{
    if(solvedNumber==h*w)    ++ans;
    else
    {
        if(stateBoard&(1<<solvedNumber))    return dfs(solvedNumber+1,stateBoard,leftLongerBlock,leftCenterBlock);
        if(leftLongerBlock)
        {
            if((solvedNumber%w!=w-1)&&(!(stateBoard&(1<<(solvedNumber+1)))))    dfs(solvedNumber+1,stateBoard|(1<<solvedNumber)|(1<<(solvedNumber+1)),leftLongerBlock-1,leftCenterBlock);
            if(solvedNumber+w<h*w)    dfs(solvedNumber+1,stateBoard|(1<<solvedNumber)|(1<<(solvedNumber+w)),leftLongerBlock-1,leftCenterBlock);
        }
        if(leftCenterBlock)    dfs(solvedNumber+1,stateBoard|(1<<solvedNumber),leftLongerBlock,leftCenterBlock-1);
    }
}
int main()
{
    cin >> h >> w >> a >> b;
    dfs(0,0,a,b); cout << ans << "\n";
    return 0;
}

「ABC 196E」Filters

Link.

这是个 Segment Tree Beats 的板子,不打了。

// Oops, something went wrong.

「ABC 196F」Substring 2

Link.

你 ABC 考 FFT 字符串匹配。

定义匹配函数 $f(x)=\sum_{i=0}^{|T|-1}(S_{x+i}-T_{i})^{2}=\sum_{i=0}^{|T|-1}S^{2}_{x+i}-2\sum_{i=0}^{|T|-1}S_{x+i}T_{i}+\sum_{i=0}^{|T|-1}T_{i}^{2}$。

然后反转 $T$ 卷积即可。

#include<cstdio>
#include<numeric>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long LL;
const int MOD=998244353,INF=numeric_limits<int>::max();
void exGCD(int one,int ano,int &x,int &y)
{
    if(ano==0)    x=1,y=0;
    else    exGCD(ano,one%ano,y,x),y-=(one/ano)*x;
}
int getInv(int val){int res,w; exGCD(val,MOD,res,w); return (res+MOD)%MOD;}
int qpow(int bas,int fur)
{
    int res=1;
    while(fur)
    {
        if(fur&1)    res=LL(res)*bas%MOD;
        bas=LL(bas)*bas%MOD;
        fur>>=1;
    }
    return res%MOD;
}
namespace Poly
{
    typedef vector<int> poly;
    #define len(x) (int((x).size()))
    int lim,rev[4000010];
    void ntt(poly &f,int op)
    {
        for(int i=0;i<lim;++i)    if(i<rev[i])    swap(f[i],f[rev[i]]);
        for(int len=2;len<=lim;len<<=1)
        {
            int bas=qpow(op==1?3:332748118,(MOD-1)/len);
            for(int fr=0;fr<lim;fr+=len)
            {
                int now=1;
                for(int ba=fr;ba<fr+(len>>1);++ba,now=LL(now)*bas%MOD)
                {
                    int tmp=LL(now)*f[ba+(len>>1)]%MOD;
                    f[ba+(len>>1)]=(f[ba]-tmp+MOD)%MOD;
                    f[ba]=(f[ba]+tmp)%MOD;
                }
            }
        }
        if(op==-1)
        {
            int tmp=getInv(lim);
            for(int i=0;i<lim;++i)    f[i]=LL(f[i])*tmp%MOD;
        }
    }
    poly operator*(poly f,poly g)
    {
        int n=len(f)+len(g)-1; lim=1;
        while(lim<n)    lim<<=1;
        f.resize(lim),g.resize(lim);
        for(int i=0;i<lim;++i)    rev[i]=(rev[i>>1]>>1)|((i&1)?(lim>>1):0);
        ntt(f,1),ntt(g,1);
        for(int i=0;i<lim;++i)    f[i]=LL(f[i])*g[i]%MOD;
        ntt(f,-1),f.resize(n);
        return f;
    }
    poly operator*(int x,poly f){for(int i=0;i<len(f);++i)    f[i]=LL(f[i])*x%MOD; return f;}
    poly operator-(poly f,poly g)
    {
        int n=max(len(f),len(g));
        f.resize(n),g.resize(n);
        for(int i=0;i<len(f);++i)    f[i]=(f[i]-g[i]+MOD)%MOD;
        return f;
    }
    poly operator+(poly f,poly g)
    {
        int n=max(len(f),len(g));
        f.resize(n),g.resize(n);
        for(int i=0;i<len(f);++i)    f[i]=(f[i]+g[i])%MOD;
        return f;
    }
}using namespace Poly;
int main()
{
    string S,T;
    cin >> S >> T; reverse(T.begin(),T.end());
    poly onesi,anosi,onexsi,anoxsi;
    #define Sqr(x) ((LL)(x)*(x)%MOD)
    onesi.push_back(Sqr((*S.begin())-'0'));
    anosi.push_back(Sqr((*T.begin())-'0'));
    for(int i=1;i<len(S);++i)    onesi.push_back(onesi.back()+Sqr(S[i]-'0'));
    for(int i=1;i<len(T);++i)    anosi.push_back(anosi.back()+Sqr(T[i]-'0'));
    for(char c : S)    onexsi.push_back(c-'0'); for(char c : T)    anoxsi.push_back(c-'0');
    poly tmp=2*onexsi*anoxsi; int ans=INF;
    #define getValue(i) (((i)<(len(T)))?0:onesi[(i)-len(T)])
    for(unsigned int i=T.size()-1;i<S.size();++i)    ans=min(ans,onesi[i]-getValue(i)+anosi[len(T)-1]-tmp[i]);
    printf("%d\n",ans);
    return 0;
}