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

标签 maths 下的文章

Description

Link.

给你一个序列,你每次可以取 $1\sim3$ 个数然后计算和,问你对于每一种和,方案数是多少。

Solution

设一个 OGF $A(x)=\sum_{i=0}^{+\infty}a_{i}x^{i}$,指数为物品的价值,$a_{i}$ 为出现的次数。

也就是说,$\sum a_{i}$ 就是选个一个数的答案。

再来考虑选两个数。$A^{2}(x)$ 显然会有重复。

重复有两种情况,第一种是 $i\times j$ 和 $j\times i$,这个简单,除个 $2!$ 即可。

还有就是 $i\times i$ 的情况,那么再设一个表示一个斧头选两次的 OGF $B(x)=\sum_{i=0}^{+\infty}b_{i}x^{2i}$。

那么选两个数的答案为 $\frac{A^{2}(x)-B(x)}{2!}$。

再来考虑选三个数,基本同理地设 $C(x)=\sum_{i=0}^{+\infty}c_{i}x^{3i}$。

然后选三个数的答案为 $\frac{A^{3}(x)-3A(x)B(x)+2C(x)}{3!}$,这个容斥就是考虑 $\sf aab,baa$ 和 $\sf abc,acb$ 情况的重复。

做完了。

#include<bits/stdc++.h>
using namespace std;
namespace Poly
{
    typedef complex<double> comp;
    typedef vector<complex<double> > poly;
    #define len(x) (int((x).size()))
    const double bh_pi=acos(-1),eps=1e-3;
    int lim,rev[500010];
    void fft(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)
        {
            comp bas(cos(2*bh_pi/len),op*sin(2*bh_pi/len));
            for(int fr=0;fr<lim;fr+=len)
            {
                comp now(1,0);
                for(int ba=fr;ba<fr+(len>>1);++ba,now*=bas)
                {
                    comp tmp=now*f[ba+(len>>1)];
                    f[ba+(len>>1)]=f[ba]-tmp;
                    f[ba]+=tmp;
                }
            }
        }
        if(op==-1)    for(int i=0;i<lim;++i)    f[i]/=lim;
    }
    poly mulPoly(poly f,poly g)
    {
        int n=len(f)+len(g)-1;
        for(lim=1;lim<n;lim<<=1);
        for(int i=0;i<lim;++i)    rev[i]=(rev[i>>1]>>1)|((i&1)?(lim>>1):0);
        f.resize(lim),g.resize(lim);
        fft(f,1),fft(g,1);
        for(int i=0;i<lim;++i)    f[i]*=g[i];
        fft(f,-1),f.resize(n);
        return f;
    }
    poly addPoly(poly f,poly g)
    {
        int n=max(len(f),len(g));
        f.resize(n),g.resize(n);
        for(int i=0;i<n;++i)    f[i]+=g[i];
        return f;
    }
    poly decPoly(poly f,poly g)
    {
        int n=max(len(f),len(g));
        f.resize(n),g.resize(n);
        for(int i=0;i<n;++i)    f[i]-=g[i];
        return f;
    }
    poly mulPoly(poly f,double x)
    {
        for(int i=0;i<len(f);++i)    f[i]*=x;
        return f;
    }
    poly divPoly(poly f,double x)
    {
        for(int i=0;i<len(f);++i)    f[i]/=x;
        return f;
    }
}using namespace Poly;
int main()
{
    int waste,x;
    scanf("%d",&waste);
    poly one,two,thr;
    while(waste--)
    {
        scanf("%d",&x);
        if(x>=len(one))    one.resize(x+1);
        if((x<<1)>=len(two))    two.resize(x<<1|1);
        if((x<<1)+x>=len(thr))    thr.resize((x<<1)+x+1);
        one[x]=comp(one[x].real()+1,0);
        two[x<<1]=comp(two[x<<1].real()+1,0);
        thr[(x<<1)+x]=comp(thr[(x<<1)+x].real()+1,0);
    }
    poly ans=addPoly(addPoly(one,divPoly(decPoly(mulPoly(one,one),two),2)),divPoly(addPoly(decPoly(mulPoly(mulPoly(one,one),one),mulPoly(mulPoly(one,two),3)),mulPoly(thr,2)),6));
    for(int i=0;i<len(ans);++i)    if(int(ans[i].real()+eps))    printf("%d %d\n",i,int(ans[i].real()+eps));
    return 0;
}

「ARC 113A」A*B*C

Link.

就是算 $\sum_{i=1}^{k}\sum_{j=1}^{\lfloor\frac{k}{i}\rfloor}\lfloor\frac{k}{j\times j}\rfloor$。

直接调和级数。

#include<cstdio>
long long k;
int main()
{
    scanf("%lld",&k);
    long long ans=0;
    for(long long i=1;i<=k;++i)
    {
        for(long long j=1;j<=k/i;++j)    ans+=(k/i/j);
    }
    printf("%lld\n",ans);
    return 0;
}

「ARC 113B」A^B^C

Link.

扩展欧拉定理裸题,$A^{B^{C}}\bmod10=A^{(B^{C}\bmod\varphi(10))+\varphi(10)}\bmod10$。

#include<cstdio>
long long getphi(long long x)
{
    long long res=x;
    for(long long i=2;i*i<=x;++i)
    {
        if(x%i==0)
        {
            res=res/i*(i-1);
            while(x%i==0)    x/=i;
        }
    }
    if(x>1)    res=res/x*(x-1);
    return res;
}
long long cqpow(long long bas,long long fur,long long mod)
{
    long long res=1;
    while(fur)
    {
        if(fur&1)    res=res*bas%mod;
        bas=bas*bas%mod;
        fur>>=1;
    }
    return res;
}
long long a,b,c;
int main()
{
    scanf("%lld %lld %lld",&a,&b,&c);
    printf("%lld\n",cqpow(a,cqpow(b,c,getphi(10))+getphi(10),10));
    return 0;
}

「ARC 113C」String Invasion

Link.

正序枚举 $i\in[1,n]$,如果满足条件,那么后面的字符串都可以执行操作,则 $ans:=ans+n-i$。

当然,由于后面可能存在一个字符就是 $s_{i}$,所以要记录当前操作的字符,特判 $ans:=ans-1$。

#include<cstdio>
#include<cstring>
int n;
long long ans;
char s[200010];
int main()
{
    scanf("%s",s+1);
    n=strlen(s+1);
    char las=0;
    for(int i=1;i<=n;++i)
    {
        if(i!=n&&s[i]==s[i+1]&&s[i]!=s[i+2]&&s[i]!=las)    ans+=n-i,las=s[i];
        else if(s[i]==las)    --ans;
    }
    printf("%lld\n",ans);
    return 0;
}

「ARC 113D」Sky Reflector

Link.

显然只要 $\forall i\in[1,m],b_{i}\ge a_{\max}$ 即可,那么枚举 $i\in[1,k]=a_{\max}$,有:

$$ ans=\sum_{i=1}^{k}(i^{n}-(i-1)^{n})\times(k-i+1)^{m}\bmod998244353 $$

#include<cstdio>
const int mod=998244353;
long long cqpow(long long bas,int fur)
{
    long long res=1;
    while(fur)
    {
        if(fur&1)    res=res*bas%mod;
        bas=bas*bas%mod;
        fur>>=1;
    }
    return res;
}
int n,m,k;
long long ans;
int main()
{
    scanf("%d %d %d",&n,&m,&k);
    if(n==1)    ans=cqpow(k,m);
    else if(m==1)    ans=cqpow(k,n);
    else
    {
        for(int i=1;i<=k;++i)    ans=(ans+((cqpow(i,n)-cqpow(i-1,n)+mod)%mod)*cqpow(k-i+1,m)%mod)%mod;
    }
    printf("%lld\n",ans);
    return 0;
}

「ARC 113E」Rvom and Rsrev

Link.

「ARC 113F」Social Distance

Link.

「CF 1485A」Add and Divide

Link.

贪心。枚举 $[b,b+\log_{2}\text{range}]$ 然后取个 $\min$。

#include<cstdio>
#include<algorithm>
using namespace std;
int t,a,b,ans;
int search(int bas)
{
    if(bas>1)
    {
        int tmp=a,res=0;
        while(tmp>0)
        {
            tmp/=bas;
            res++;
        }
        return res;
    }
    else    return 1e9;
}
int main()
{
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d %d",&a,&b);
        if(a==b)    printf("%d\n",2);
        else if(a<b)    printf("%d\n",1);
        else
        {
            ans=1e9;
            for(int i=b;i<=b+233;++i)    ans=min(ans,search(i)+i-b);
            printf("%d\n",ans);
        }
    }
    return 0;
}

「CF 1485B」Replace and Keep Sorted

Link.

每个元素都可以上下摇摆于是预处理前缀差分和和后缀差分和(因为是 strictly increasing 所以要减 $1$)即可。

#include<cstdio>
int n,m,k,a[100010],fro[100010],rea[100010];
void pre()
{
    for(int i=1;i<=n;++i)    fro[i]=a[i]-a[i-1]-1;
    for(int i=n;i>=1;--i)    rea[i]=a[i+1]-a[i]-1;
    for(int i=1;i<=n;++i)    fro[i]+=fro[i-1];
    for(int i=n;i>=1;--i)    rea[i]+=rea[i+1];
}
int main()
{
    scanf("%d %d %d",&n,&m,&k);
    for(int i=1;i<=n;++i)    scanf("%d",&a[i]);
    pre();
    while(m--)
    {
        int l,r;
        scanf("%d %d",&l,&r);
        printf("%d\n",k-a[r]+a[l]-1+fro[r]-fro[l]+rea[l]-rea[r]);
    }
    return 0;
}

「CF 1485C」Floor and Mod

Link.

$$ a\bmod b=\lfloor\frac{a}{b}\rfloor=k \\ \rightarrow a=kb+k\rightarrow a=(b+1)k\rightarrow k=\frac{a}{b+1} \\ k<b\rightarrow k^{2}<k(b+1)=a\le x\rightarrow 1\le k\le\sqrt{x} \\ 1\le a\le x\rightarrow 1\le(b+1)k\le x\rightarrow1\le b\le\frac{x}{k}-1 \\ \rightarrow\text{ans}=\sum_{k=1}^{\sqrt{x}}\max(0,\min(y,\frac{x}{k}-1)-k) $$

#include<cstdio>
#include<algorithm>
using namespace std;
const long long zero=0ll;
long long t,x,y,ans;
int main()
{
    scanf("%lld",&t);
    while(t--)
    {
        scanf("%lld %lld",&x,&y);
        ans=0;
        for(long long i=1;i*i<=x;++i)    ans+=max(zero,min(y,x/i-1)-i);
        printf("%lld\n",ans);
    }
    return 0;
}

「CF 1485D」Multiples and Power Differences

Link.

  • $(i+j)\bmod 2=1$:$b_{i,j}=\text{lcm}(1,\cdots,16)$。
  • $(i+j)\bmod 2=0$:$b_{i,j}=\text{lcm}(1,\cdots,16)+a_{i,j}^{4}$。

#include<cstdio>
int n,m,x;
int main()
{
    scanf("%d %d",&n,&m);
    for(int i=1;i<=n;++i)
    {
        for(int j=1;j<=m;++j)
        {
            scanf("%d",&x);
            if((i+j)&1)    printf("%d ",720720);
            else    printf("%d ",720720+x*x*x*x);
        }
        printf("\n");
    }
    return 0;
}

「CF 1485E」Move and Swap

Link.

blue 因为就是一直往下跑,所以一次操作在哪里不影响。

于是设 $f_{u}$ 为操作完毕后 red 跑到 $u$ 的 maximum value。

  • $v\in\text{son}(u)$ 为 red:此时没发生 swapping,$f_{u}=f_{v}+|a_{u}-a_{v}|$。
  • $v\in\text{son}(u)$ 为 blue:此时发生了 swapping,那么枚举 $v$ 的同层结点 $anov$,$f_{u}=f_{anov}+|a_{u}-a_{anov}|$。

#include<queue>
#include<cstdio>
#include<algorithm>
using namespace std;
const long long INF=1e18;
vector<int> e[200010],same[200010];
int t,n,dep[200010],fa[200010],leaf;
long long a[200010],f[200010];
void dfs(int x,int las)
{
    dep[x]=dep[las]+1;
    fa[x]=las;
    leaf=max(leaf,dep[x]);
    for(int i=0;i<e[x].size();++i)
    {
        int y=e[x][i];
        if(y^las)    dfs(y,x);
    }
}
void DP(int d)
{
    for(int i=d;i>1;--i)
    {
        long long mn=INF,mx=-INF,one=-INF,ano=-INF;
        for(int j=0;j<same[i].size();++j)
        {
            mn=min(mn,a[same[i][j]]);
            mx=max(mx,a[same[i][j]]);
        }
        for(int j=0;j<same[i].size();++j)    f[fa[same[i][j]]]=max(f[fa[same[i][j]]],max(a[same[i][j]]-mn,mx-a[same[i][j]])+f[same[i][j]]);
        for(int j=0;j<same[i].size();++j)
        {
            one=max(one,f[same[i][j]]+a[same[i][j]]);
            ano=max(ano,f[same[i][j]]-a[same[i][j]]);
        }
        for(int j=0;j<same[i].size();++j)    f[fa[same[i][j]]]=max(f[fa[same[i][j]]],max(one-a[same[i][j]],ano+a[same[i][j]]));
    }
}
int main()
{
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&n);
        for(int i=2;i<=n;++i)
        {
            int x;
            scanf("%d",&x);
            e[x].push_back(i);
            e[i].push_back(x);
        }
        for(int i=2;i<=n;++i)    scanf("%d",&a[i]);
        dfs(1,0);
        for(int i=1;i<=n;++i)    same[dep[i]].push_back(i);
        DP(leaf);
        printf("%lld\n",f[1]);
        for(int i=1;i<=n;++i)
        {
            f[i]=dep[i]=fa[i]=0;
            same[i].clear();
            e[i].clear();
        }
        leaf=0;
    }
    return 0;
}

「CF 1485F」Copy or Prefix Sum

Link.

Description

Link.

$\operatorname{Rainyrabbit}$ 是一个数学极好的萌妹子,近期他发现了一个可爱的函数:

$$ f(n,m,k)=\sum_{d=1}^n d^k\lfloor\dfrac{n}{\operatorname{lcm}(d,m)}\rfloor $$

其中 $\operatorname{lcm}(d,m)$ 表示 $d$ 和 $m$ 的最小公倍数。

她觉得只算这一个函数太单调了于是想要对这个函数求和,给出 $a,b,c$,求:

$$ \sum_{i=1}^a\sum_{j=1}^b\sum_{k=0}^cf(i,j,k) $$

同时 $\operatorname{I.w.rabbit}$ 固定 $c$ 的值不变,给出 $T$ 组 $a,b$,请回答此时式子对 $998244353$ 取模后的值。

算是概括过了额。

Solution

先看 $f$ 怎么把那个烦死的整除去掉。

$$ \begin{aligned} f(n,m,k)&=\sum_{d=1}^{n}d^{k}\lfloor\frac{n}{\text{lcm}(d,m)}\rfloor \\ &=\sum_{d=1}^{n}d^{k}\lfloor\frac{\frac{n}{d}}{\frac{m}{\gcd(d,m)}}\rfloor \\ &=\sum_{d=1}^{n}d^{k}\lfloor\frac{\frac{n}{d}}{\frac{m}{\gcd(d,m)}}\rfloor \\ \end{aligned} $$

来看 $\lfloor\frac{\frac{n}{d}}{\frac{m}{\gcd(d,m)}}\rfloor$,因为 $\lfloor\frac{a}{b}\rfloor=\sum_{i=1}^{a}[b|i]$,所以 $\lfloor\frac{\frac{n}{d}}{\frac{m}{\gcd(d,m)}}\rfloor=\sum_{i=1}^{\lfloor\frac{n}{d}\rfloor}[\frac{m}{\gcd(d,m)}|i]=\sum_{i=1}^{\lfloor\frac{n}{d}\rfloor}[m|id]$。所以

$$ \begin{aligned} f(n,m,k)&=\sum_{d=1}^{n}d^{k}\lfloor\frac{\frac{n}{d}}{\frac{m}{\gcd(d,m)}}\rfloor \\ &=\sum_{d=1}^{n}d^{k}\sum_{i=1}^{\lfloor\frac{n}{d}\rfloor}[m|id] \\ &=\sum_{m|i}^{n}\sum_{d|i}d^{k} \\ &=\sum_{m|i}^{n}\sigma_{k}(i) \\ \end{aligned} $$

然后代回原式。

$$ \begin{aligned} \sum_{i=1}^{a}\sum_{j=1}^{b}\sum_{k=0}^{c}\sum_{j|d}^{i}\sigma_{k}(d)&=\sum_{k=0}^{c}\sum_{d=1}^{a}\sigma_{k}(d)(a-d+1)\sum_{j=1}^{b}[j|d] \\ \end{aligned} $$

考虑如何计算 $\sum_{k=0}^{c}\sigma_{k}(d)$。把函数又拆回去:

$$ \begin{aligned} \sum_{k=0}^{c}\sigma_{k}(d)&=\sum_{w|d}\sum_{k=0}^{c}w^{k}=\sum_{w|d}\frac{w^{c+1}-1}{w-1} \end{aligned} $$

最后一步是等比数列求和,然后你就可以调和级数预处理了。具体来说就是线筛的时候筛一下 $w^{c+1}$,这东西是个完全积性函数,你乱筛就行了。

设这玩意儿为 $s(d)=\sum_{w|d}\frac{w^{c+1}-1}{w-1}$,原式改写为:

$$ \sum_{d=1}^{a}s(d)(a-d+1)\sum_{j=1}^{b}[j|d] \\ $$

然后后面那个 sigma 你也可以反过来直接调和级数。还有就是 $b>a$ 的时候没有贡献,所以可以取个 $\min$,这样能多几分。

来看看怎么屮多测。

数表 那道题一样,我们把询问离线下来,以 $b$ 为关键字排序后树状数组。

把中间那个系数拆出来,变成:

$$ \sum_{d=1}^{a}(a+1)s(d)-d\times s(d)\sum_{j=1}^{b}[j|d] \\ $$

前面那个好说,直接来;后面就在树状数组修改时乘上系数即可。

综上,维护两个树状数组即可。

#include<cstdio>
#include<algorithm>
using namespace std;
void read(long long &x)
{
    x=0;
    char c=getchar();
    while(c<'0'||c>'9')    c=getchar();
    while(c>='0'&&c<='9')
    {
        x=(x<<3)+(x<<1)+(c^'0');
        c=getchar();
    }
}
void write(long long x)
{
    if(x>9)    write(x/10);
    putchar((x%10)^'0');
}
const long long mod=998244353;
struct node
{
    long long a,b,ID;
}nodes[200010];
struct fenwick
{
    #define lowbit(x) ((x)&-(x))
    long long fen[1000010],mx;
    void ins(long long x,long long y)
    {
        while(x<=mx)
        {
            fen[x]=(fen[x]+y)%mod;
            x+=lowbit(x);
        }
    }
    long long find(long long x)
    {
        long long res=0;
        while(x)
        {
            res=(res+fen[x])%mod;
            x^=lowbit(x);
        }
        return res;
    }
}onefe,anofe;
long long t,a,b,c,tag[1000010],prime[1000010],cnt,fu[1000010],exfu[1000010],power[1000010],cur=1,mx,ans[200010];
bool cmp(node one,node ano)
{
    return one.b<ano.b;
}
long long cqpow(long long bas,long long fur)
{
    long long res=1;
    while(fur)
    {
        if(fur&1)    res=res*bas%mod;
        bas=bas*bas%mod;
        fur>>=1;
    }
    return res;
}
void search(long long x)
{
    tag[1]=power[1]=1;
    for(long long i=2;i<=x;++i)
    {
        if(!tag[i])
        {
            prime[++cnt]=i;
            power[i]=cqpow(i,c+1);
        }
        for(long long j=1;j<=cnt&&prime[j]*i<=x;++j)
        {
            tag[prime[j]*i]=1;
            power[prime[j]*i]=power[prime[j]]*power[i]%mod;
            if(i%prime[j]==0)    break;
        }
    }
    fu[1]=(c%mod+1)%mod;
    for(long long i=2;i<=x;++i)    fu[i]=((power[i]-1+mod)%mod)*cqpow(i-1,mod-2)%mod;
    for(long long i=1;i<=x;++i)
    {
        for(long long j=i;j<=x;j+=i)    exfu[j]=(exfu[j]+fu[i])%mod;
    }
}
int main()
{
    read(t);
    read(c);
    search(1000000);
    for(long long i=1;i<=t;++i)
    {
        read(nodes[i].a);
        read(nodes[i].b);
        nodes[i].ID=i;
        nodes[i].b=min(nodes[i].a,nodes[i].b);
        mx=max(mx,nodes[i].a);
    }
    sort(nodes+1,nodes+t+1,cmp);
    onefe.mx=anofe.mx=mx;
    for(long long i=1;i<=mx&&cur<=t;++i)
    {
        for(long long j=i;j<=mx;j+=i)
        {
            onefe.ins(j,exfu[j]);
            anofe.ins(j,exfu[j]*j%mod);
        }
        while(i==nodes[cur].b)
        {
            ans[nodes[cur].ID]=((onefe.find(nodes[cur].a)*(nodes[cur].a+1))%mod-anofe.find(nodes[cur].a)+mod)%mod;
            cur++;
        }
    }
    for(long long i=1;i<=t;++i)
    {
        write(ans[i]);
        putchar('\n');
    }
    return 0;
}

「ARC 111A」Simple Math 2

Link.

$\lfloor \frac{10^N - kM^2}{M} \rfloor \equiv \lfloor \frac{10^N}{M} - kM \rfloor \equiv \lfloor \frac{10^N}{M} \rfloor - kM \equiv \lfloor \frac{10^N}{M} \rfloor \pmod M (k \in \mathbb{Z})$

#include <iostream>

using i64 = long long;

int cpow ( int bas, i64 idx, const int p ) {
    int res = 1;
    while ( idx ) {
        if ( idx & 1 )    res = ( i64 )res * bas % p;
        bas = ( i64 )bas * bas % p, idx >>= 1;
    }
    return res;
}

int main () {
    std::ios::sync_with_stdio ( 0 ); std::cin.tie ( 0 ); std::cout.tie ( 0 );
    i64 n; int m; std::cin >> n >> m;
    std::cout << ( cpow ( 10, n, m * m ) / m ) % m << '\n';
    return 0;
}

「ARC 111B」Reversible Cards

Link.

nowcoder 原题。

#include<cstdio>
int n,cab[400010],fa[400010],a,b,ans;
int findset(int x)
{
    if(fa[x])    return fa[x]=findset(fa[x]);
    else    return x;
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;++i)
    {
        scanf("%d%d",&a,&b);
        a=findset(a);
        b=findset(b);
        if((a^b)&&(!cab[a]||!cab[b]))
        {
            fa[a]=b;
            cab[b]|=cab[a];
            ans++;
        }
        else if(!cab[a])
        {
            cab[a]=1;
            ans++;
        }
    }
    printf("%d\n",ans);
    return 0;
}

「ARC 111C」Too Heavy

Link.

构造出一个操作序列。

先不考虑最小,只考虑构造出来。

参考某道 ABC D 题,直接连边。

$i\rightarrow p_{i}\rightarrow p_{p_{i}}\rightarrow\cdots\rightarrow i$。

craft.png

$1\ 2$ 分别表示 person、baggage。

再想,相当于我们想要让,$1$ and $2$ 一一对应。

一个 $(u,v)$ 的 $2$(即 $v$)不能被交换只在 $a_{u}\le b_{v}$。

所以无解就是这个环中存在 $a_{u}\le b_{v}$。

剩下构造,先考虑满足规则。

贪心的选一个最大的 $a_{i}$ 进行即可。

#include<queue>
#include<cstdio>
#include<algorithm>
using namespace std;
vector<pair<int,int> > ans;
int n,a[200010],b[200010],p[200010],rev[200010],vis[200010];
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;++i)    scanf("%d",&a[i]);
    for(int i=1;i<=n;++i)    scanf("%d",&b[i]);
    for(int i=1;i<=n;++i)
    {
        scanf("%d",&p[i]);
        rev[p[i]]=i;
    }
    vector<int> per;
    for(int i=1;i<=n;++i)
    {
        if(p[i]^i)
        {
            if(a[rev[i]]<=b[i])
            {
                printf("-1\n");
                return 0;
            }
            if(!vis[i])
            {
                vis[i]=1;
                per.clear();
                per.push_back(i);
                for(int j=p[i];j^i;j=p[j])
                {
                    if(a[rev[j]]<=b[j])
                    {
                        printf("-1\n");
                        return 0;
                    }
                    vis[j]=1;
                    per.push_back(j);
                }
                int pos=0,val=0;
                for(int j=0;j<per.size();++j)
                {
                    if(a[per[pos]]<=a[per[j]])
                    {
                        pos=j;
                        val=per[j];
                    }
                }
                for(int j=pos+1;j<per.size();++j)    ans.push_back(make_pair(val,per[j]));
                for(int j=0;j<pos;++j)    ans.push_back(make_pair(val,per[j]));
            }
        }
    }
    printf("%d\n",ans.size());
    for(int i=0;i<ans.size();++i)    printf("%d %d\n",ans[i].first,ans[i].second);
    return 0;
}

「ARC 111D」Orientation

Link.

像个贪心?

  • $c_{u}\neq c_{v}$

    • $c_{u}>c_{v}$:$\rightarrow$
    • $c_{u}<c_{v}$:$\leftarrow$
  • $c_{u}=c_{v}$

在一个环里,深搜即可。

这 C D 放反了吧

#include<queue>
#include<cstdio>
#include<string>
#include<algorithm>
using namespace std;
vector<pair<int,int> > e[110];
vector<string> ans;
int n,m,c[110],eve[110][110],vis[110];
void dfs(int x)
{
    vis[x]=1;
    for(int i=1;i<=n;++i)
    {
        if(eve[x][i])
        {
            eve[i][x]=0;
            if(!vis[i])    dfs(i);
        }
    }
}
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;++i)
    {
        int u,v;
        scanf("%d%d",&u,&v);
        e[u].push_back(make_pair(v,i));
    }
    for(int i=1;i<=n;++i)    scanf("%d",&c[i]);
    ans.resize(m);
    for(int i=1;i<=n;++i)
    {
        for(int j=0;j<e[i].size();++j)
        {
            int y=e[i][j].first,id=e[i][j].second-1;
            if(c[i]>c[y])    ans[id]="->";
            else if(c[i]<c[y])    ans[id]="<-";
            else    eve[i][y]=eve[y][i]=1;
        }
    }
    for(int i=1;i<=n;++i)
    {
        for(int j=0;j<e[i].size();++j)
        {
            int y=e[i][j].first,id=e[i][j].second-1;
            dfs(i);
            if(eve[i][y])    ans[id]="->";
            else if(eve[y][i])    ans[id]="<-";
        }
    }
    for(int i=0;i<ans.size();++i)    printf("%s\n",ans[i].c_str());
    return 0;
}

「ARC 111E」Simple Math 3

Link.

即求:

$$ \sum_{i=1}^{\infty}[\lfloor\frac{A+B\times i-1}{D}\rfloor=\lfloor\frac{A+C\times i}{D}\rfloor] $$

题目说这玩意儿是 finite,然后(没加思考)跑到 U 群问成功丢人。

悲伤的故事,这告诉我们问前先思考。

原因是 $i$ 大了 $[A+B\times i,A+C\times i]$ 的长度一定 $\ge D$。

具体来说是 $i>\frac{D-2}{C-B}$ 的时候就完了。

那么式子改写为:

$$ \sum_{i=1}^{\frac{D-2}{C-B}}[\lfloor\frac{A+B\times i-1}{D}\rfloor=\lfloor\frac{A+C\times i}{D}\rfloor] $$

继续分析,此时的区间 $[A+B\times i,A+C\times i]$ 的长度小于 $D$,里面最多有一个数是 $D$ 的 multiple。

不会了 看题解 要类欧 不会了 抄板子 过题了

这种推不复杂考板的题好草人啊。。。。

upd:

official editorial 说可以用 AC lib 的 floor_sum 直接算。

屑行为 details

#include<cstdio>
int T;
long long a,b,c,d;
long long dfs(long long a,long long b,long long c,long long n)
{
    if(a>=c||b>=c)    return dfs(a%c,b%c,c,n)+(a/c)*(n+1)*n/2+(b/c)*(n+1);
    else if(a==0)    return 0;
    else    return (a*n+b)/c*n-dfs(c,c-b-1,a,(a*n+b)/c-1);
}
int main()
{
    scanf("%d",&T);
    while(T--)
    {
        scanf("%lld%lld%lld%lld",&a,&b,&c,&d);
        printf("%lld\n",(d-2)/(c-b)-dfs(c,a,d,(d-2)/(c-b))+dfs(b,a-1,d,(d-2)/(c-b)));
    }
    return 0;
}

「ARC 111A」Simple Math 2

Link.

missing。