AtCoder Regular Contest 111

A Simple Math 2

1 0 n m   m o d   m = 1 0 n   m o d   m 2 + k ∗ m 2 m   m o d   m \frac{10^n}{m}\bmod m=\frac{10^n\bmod m^2+k*m^2}{m}\bmod m m10nmodm=m10nmodm2+km2modm
Meanwhile, k ∗ m 2 m   m o d   m = 0 \frac{k*m^2}{m}\bmod m=0 mkm2modm=0
Then the answer is 1 0 n   m o d   m 2 m   m o d   m \frac{10^n\bmod m^2}{m}\bmod m m10nmodm2modm

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll n,m;
ll qpow(ll a,ll n,ll mod)
{
    ll ans=1;
    for(;n;n>>=1,a=a*a%mod)
        if(n&1) ans=ans*a%mod;
    return ans;
}
int main()
{
    cin>>n>>m;
    int r=qpow(10,n,m);
    int ans=qpow(10,n,m*m);
    ans=ans/m%m;
    printf("%d\n",ans);
}

B Reversible Cards

2020牛客多校I。
https://ac.nowcoder.com/acm/contest/5673/I

C Too Heavy

i i i现在背的包是 p j p_j pj的包,可以得到一个环 i → p i → p p i → . . . → i i\rightarrow p_i\rightarrow p_{p_i}\rightarrow...\rightarrow i ipippi...i。如果环长度只有 1 1 1,略过。
只要环中有一个 b p i ≥ a i b_{p_i}\ge a_i bpiai的,答案就是 − 1 -1 1
否则,令环的序列为 i 1 , i 2 , i 3 , . . , i k i_1,i_2,i_3,..,i_k i1,i2,i3,..,ik,有 m a x ( a i 1 , . . , a i k ) > m a x ( b i 1 , . . , b i k ) max(a_{i_1},..,a_{i_k})>max(b_{i_1},..,b_{i_k}) max(ai1,..,aik)>max(bi1,..,bik)
只需要每次和 a a a最大的那个位置交换即可。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e5+5;
int n,a[N],b[N],p[N];
bool vis[N];
vector<int>v;
vector<pair<int,int>>ans;
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]);
    for(int i=1;i<=n;i++)
        if(!vis[i])
    {
        vis[i]=true;
        if(p[i]==i) continue;
        if(b[p[i]]>=a[i])
        {
            printf("-1\n");
            return 0;
        }
        v.clear();
        v.push_back(i);
        vis[i]=true;
        for(int j=p[i];j!=i;j=p[j])
        {
            if(b[p[j]]>=a[j])
            {
                printf("-1\n");
                return 0;
            }
            v.push_back(j);
            vis[j]=true;
        }
        int pos=0;
        for(int i=1;i<v.size();i++)
            if(a[v[i]]>a[v[pos]]) pos=i;
        for(int i=pos+1;i<v.size();i++)
            ans.push_back({v[i],v[pos]});
        for(int i=0;i<pos;i++)
            ans.push_back({v[i],v[pos]});
    }
    printf("%d\n",ans.size());
    for(pair<int,int>x:ans)
        printf("%d %d\n",x.first,x.second);
}

D Orientation

一条边 u , v u,v u,v,如果 c v ≠ c u c_v\neq c_u cv=cu,连边显然。否则,它们在同一个强连通分量里,只需要模仿 t a r j a n tarjan tarjan进行一次 d f s dfs dfs即可,因为数据保证有解。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=105;
int n,m,a[N*N],b[N*N],c[N],mp[N][N];
string ans[N*N];
bool vis[N];
void dfs(int u)
{
    vis[u]=true;
    for(int i=1;i<=n;i++)
    {
        if(mp[u][i])
        {
            mp[i][u]=false;
            if(!vis[i]) dfs(i);
        }
    }
}
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++)
    {
        scanf("%d%d",&a[i],&b[i]);
    }
    for(int i=1;i<=n;i++) scanf("%d",&c[i]);
    for(int i=1;i<=m;i++)
        if(c[a[i]]>c[b[i]])
        ans[i]="->";
        else if(c[b[i]]>c[a[i]])
        ans[i]="<-";
        else mp[a[i]][b[i]]=mp[b[i]][a[i]]=true;
    for(int i=1;i<=n;i++)
        if(!vis[i]) dfs(i);
    for(int i=1;i<=m;i++)
        if(mp[a[i]][b[i]]) ans[i]="->";
    else if(mp[b[i]][a[i]]) ans[i]="<-";
    for(int i=1;i<=m;i++)
        cout<<ans[i]<<'\n';
}

E Simple Math 3

显然问题等价于求:
∑ i = 1 k [ ⌊ ( A − 1 + B ∗ i ) D ⌋ = ⌊ ( A + C ∗ i ) D ⌋ ] \sum\limits_{i=1}^{k}[\lfloor\frac{(A-1+B*i)}{D}\rfloor=\lfloor\frac{(A+C*i)}{D}\rfloor] i=1k[D(A1+Bi)=D(A+Ci)],当 k > ⌊ D − 2 C − B ⌋ k>\lfloor\frac{D-2}{C-B}\rfloor k>CBD2两边一定不相等,因为它们直接的距离相差大于等于 D D D
否则,注意到 ⌊ ( A − 1 + B ∗ i ) D ⌋ ≤ ⌊ ( A + C ∗ i ) D ⌋ \lfloor\frac{(A-1+B*i)}{D}\rfloor\le \lfloor\frac{(A+C*i)}{D}\rfloor D(A1+Bi)D(A+Ci),且当 k ≤ ⌊ D − 2 C − B ⌋ k\le\lfloor\frac{D-2}{C-B}\rfloor kCBD2,他们的差最多为 1 1 1。也就是差为 1 1 1的个数等于不相等的个数。
注意到这个,答案就是 ∑ i = 1 k ⌊ ( A + C ∗ i ) D ⌋ − ⌊ ( A − 1 + B ∗ i ) D ⌋ \sum\limits_{i=1}^k\lfloor\frac{(A+C*i)}{D}\rfloor-\lfloor\frac{(A-1+B*i)}{D}\rfloor i=1kD(A+Ci)D(A1+Bi)
这是类欧几里得算法模板。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll A,B,C,D;
const int mod=998244353;
ll n,a,b,c;
struct node
{
    ll f,g,h;
    node(ll f=0,ll g=0,ll h=0):f(f),g(g),h(h){}
};
ll qpow(ll a,ll n)
{
    ll ans=1;
    for(;n;n>>=1,a=a*a%mod)
        if(n&1) ans=ans*a%mod;
    return ans;
}
const ll inv6=qpow(6,mod-2),inv2=mod-mod/2;
ll hs(ll a,ll b){return a*2000000000+b;}
ll s2(ll x){return x*(x+1)/2%mod;}
ll s3(ll x){return x*(x+1)%mod*(2*x+1)%mod*inv6%mod;}
node F(ll a,ll b,ll c,ll n)
{
    if(c==0||a==0&&b<c) return node(0,0,0);
    if(n==0) return node(b/c,0,b/c*(b/c)%mod);
    node ans;
    if(a>=c||b>=c)
    {
        node res=F(a%c,b%c,c,n);
        ans.f=(a/c*s2(n)%mod+b/c*(n+1)%mod+res.f)%mod;
        ans.g=(res.g+a/c*s3(n)%mod+b/c*s2(n)%mod)%mod;
        ans.h=(res.h+a/c*2%mod*res.g+b/c*2%mod*res.f)%mod;
        ans.h=(ans.h+(a/c)*(a/c)%mod*s3(n)+(b/c)*(b/c)%mod*(n+1))%mod;
        ans.h=(ans.h+(a/c)*(b/c)%mod*2%mod*s2(n))%mod;
    }
    else
    {
        ll m=(a*n+b)/c;
        node res=F(c,c-b-1,a,m-1);
        ans.f=(n*m%mod-res.f+mod)%mod;
        ans.g=(s2(n)*m%mod-res.h*inv2%mod-res.f*inv2%mod+mod+mod)%mod;
        ans.h=n*m%mod*(m+1)%mod-2*res.g%mod-2*res.f%mod-ans.f;
        ans.h=(ans.h%mod+mod)%mod;
    }
    return ans;
}
int main()
{
    int T;scanf("%d",&T);
    while(T--)
    {
        scanf("%lld%lld%lld%lld",&A,&B,&C,&D);
        int up=(D-2)/(C-B);
        node ans1=F(B,A-1,D,up),ans2=F(C,A,D,up);
        ll ans=(ans2.f-ans1.f+mod)%mod;
        if(A/D!=(A-1)/D) ans--;
        ans=up-ans;
        printf("%lld\n",ans);
    }
}

F Do you like query problems?

a n s = 期 望 值 ∗ 方 案 数 ans=期望值*方案数 ans=,因此只计算其期望 E E E即可。
对于一个固定的位置 i i i,其被操作的概率为 P i = i ∗ ( n − i + 1 ) ∗ 2 n ∗ ( n + 1 ) P_i=\frac{i*(n-i+1)*2}{n*(n+1)} Pi=n(n+1)i(ni+1)2,只需解决以下问题即可:
给定两个数 x , s u m i x,sum_i x,sumi初始都为 0 0 0,随机进行 q q q次操作,每次操作:

  1. 1 − P i 1-P_i 1Pi概率什么都不做
  2. P i ∗ 1 2 ∗ m + 1 P_i*\frac{1}{2*m+1} Pi2m+11的概率使得 s u m i = s u m i + x sum_i=sum_i+x sumi=sumi+x
  3. P i ∗ 1 2 ∗ m + 1 P_i*\frac{1}{2*m+1} Pi2m+11的概率使得 x = m i n ( x , v ) ( v ∈ { 0 , 1 , . . . , m − 1 } ) x=min(x,v)(v\in\{0,1,...,m-1\}) x=min(x,v)(v{0,1,...,m1})
  4. P i ∗ 1 2 ∗ m + 1 P_i*\frac{1}{2*m+1} Pi2m+11的概率使得 x = m a x ( x , v ) ( v ∈ { 0 , 1 , . . . , m − 1 } ) x=max(x,v)(v\in\{0,1,...,m-1\}) x=max(x,v)(v{0,1,...,m1})

s u m i sum_i sumi的期望值是多少。
p j , v p_{j,v} pj,v为第 j j j次操作后 x = v x=v x=v的概率。 p j , ≥ v p_{j,\ge v} pj,v为第 j j j次操作后 x ≥ v x\ge v xv的概率。则 s u m i = ∑ j = 0 q − 1 ∑ v = 0 m − 1 p j , v ∗ v ∗ P i ∗ 1 2 ∗ m + 1 = ∑ j = 0 q − 1 ∑ v = 1 m − 1 p j , ≥ v ∗ P i ∗ 1 2 ∗ m + 1 p j + 1 , ≥ v = p j , ≥ v ∗ ( 1 − P i ) + P i ∗ p j , ≥ v ∗ m + 1 + m − v 2 ∗ m + 1 + P i ∗ ( 1 − p j , ≥ v ) ∗ m − v 2 ∗ m + 1 = p j , ≥ v ∗ ( 1 − m 2 ∗ m + 1 ∗ P i ) + P i ∗ m − v 2 ∗ m + 1 sum_i=\sum\limits_{j=0}^{q-1}\sum\limits_{v=0}^{m-1}p_{j,v}*v*P_i*\frac{1}{2*m+1}\\=\sum\limits_{j=0}^{q-1}\sum\limits_{v=1}^{m-1}p_{j,\ge v}*P_i*\frac{1}{2*m+1}\\p_{j+1,\ge v}=p_{j,\ge v}*(1-P_i)+P_i*p_{j,\ge v}*\frac{m+1+m-v}{2*m+1}+\\ P_i*(1-p_{j,\ge v})*\frac{m-v}{2*m+1}=\\p_{j,\ge v}*(1-\frac{m}{2*m+1}*P_i)+P_i*\frac{m-v}{2*m+1} sumi=j=0q1v=0m1pj,vvPi2m+11=j=0q1v=1m1pj,vPi2m+11pj+1,v=pj,v(1Pi)+Pipj,v2m+1m+1+mv+Pi(1pj,v)2m+1mv=pj,v(12m+1mPi)+Pi2m+1mv
a i = 1 − m 2 ∗ m + 1 ∗ P i , b v = m − v 2 ∗ m + 1 a_i=1-\frac{m}{2*m+1}*P_i,b_v=\frac{m-v}{2*m+1} ai=12m+1mPi,bv=2m+1mv,可以得到 p 0 , ≥ v = 0 ( v ≥ 1 ) p j + 1 , ≥ v = p j , ≥ v ∗ a i + P i ∗ b v p_{0,\ge v}=0(v\ge 1)\\ p_{j+1,\ge v}=p_{j,\ge v}*a_i+P_i*b_v p0,v=0(v1)pj+1,v=pj,vai+Pibv
观察该式子可以发现 p j , ≥ v = P i ∗ b v ∗ ∑ k = 0 j − 1 a i j ( j ≥ 1 ) p_{j,\ge v}=P_i*b_v*\sum\limits_{k=0}^{j-1}a_i^j(j\ge 1) pj,v=Pibvk=0j1aij(j1)
则可以得到 E = ∑ i = 1 n s u m i = ∑ i = 1 n ∑ v = 1 m − 1 ∑ j = 1 q − 1 ∗ P i ∗ 1 2 ∗ m + 1 P i ∗ b v ∗ ∑ k = 0 j − 1 a i j = 1 2 ∗ m + 1 ∗ ( ∑ v = 1 m − 1 b v ) ∗ ∑ i = 1 n P i 2 ( ∑ j = 1 q − 1 ∑ k = 0 j − 1 a i j ) E=\sum_{i=1}^nsum_i=\sum_{i=1}^n\sum_{v=1}^{m-1}\sum_{j=1}^{q-1}*P_i*\frac{1}{2*m+1}P_i*b_v*\sum_{k=0}^{j-1}a_i^j\\=\frac{1}{2*m+1}*(\sum_{v=1}^{m-1}b_v)*\sum_{i=1}^nP_i^2(\sum_{j=1}^{q-1}\sum_{k=0}^{j-1}a_i^j) E=i=1nsumi=i=1nv=1m1j=1q1Pi2m+11Pibvk=0j1aij=2m+11(v=1m1bv)i=1nPi2(j=1q1k=0j1aij)
( ∑ j = 1 q − 1 ∑ k = 0 j − 1 a i j ) (\sum_{j=1}^{q-1}\sum_{k=0}^{j-1}a_i^j) (j=1q1k=0j1aij)可以设计矩阵快速幂 O ( l o g n ) O(logn) O(logn)计算,或者经过数学推导可以证明: ( ∑ j = 1 q − 1 ∑ k = 0 j − 1 a i j ) = q − 1 − a i ( 1 − a i q − 1 ) 1 − a i 1 − a i (\sum_{j=1}^{q-1}\sum_{k=0}^{j-1}a_i^j)=\frac{q-1-\frac{a_i(1-a_i^{q-1})}{1-a_i}}{1-a_i} (j=1q1k=0j1aij)=1aiq11aiai(1aiq1)
从而整个过程只需要枚举 i i i,时间复杂度为 O ( n l o g n ) O(nlogn) O(nlogn)
最后答案为 E ∗ ( n ∗ ( n + 1 ) 2 ∗ ( 2 ∗ m + 1 ) ) q E*(\frac{n*(n+1)}{2}*(2*m+1))^q E(2n(n+1)(2m+1))q

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=4e5+5,mod=998244353;
int n,m,q;
ll inv[N];
ll qpow(ll a,ll n)
{
    ll ans=1;
    for(;n;n>>=1,a=a*a%mod)
        if(n&1) ans=ans*a%mod;
    return ans;
}
struct node
{
    int n,m;
    node(int n=0,int m=0):n(n),m(m){memset(a,0,sizeof(a));}
    ll a[4][4];
    node operator*(const node&o)const
    {
        node ans(n,o.m);
        for(int i=1;i<=n;i++)
            for(int j=1;j<=o.m;j++)
            for(int k=1;k<=m;k++)
            ans.a[i][j]=(ans.a[i][j]+a[i][k]*o.a[k][j])%mod;
        return ans;
    }
};
node qpow(node a,ll n)
{
    node ans(a.n,a.n);
    for(int i=1;i<=a.n;i++) ans.a[i][i]=1;
    for(;n;n>>=1,a=a*a)
        if(n&1) ans=ans*a;
    return ans;
}
int main()
{
    inv[1]=1;for(int i=2;i<N;i++) inv[i]=(mod-mod/i)*inv[mod%i]%mod;
    cin>>n>>m>>q;
    ll ans=qpow(1ll*n*(n+1)/2%mod*(2*m%mod+1)%mod,q)%mod;
    ll sum=0;
    for(int v=1;v<m;v++)
        sum=(sum+(m-v)%mod*inv[2*m+1])%mod;
    ans=ans*sum%mod*inv[2*m+1]%mod;
    ll E=0;
    for(int i=1;i<=n;i++)
    {
        ll p=1ll*i*(n-i+1)%mod*inv[n]%mod*inv[n+1]%mod*2%mod;
        ll a=1-m*inv[2*m+1]%mod*p%mod;
        a=(a%mod+mod)%mod;
        //node A(3,3);
        //A.a[1][1]=A.a[2][1]=A.a[2][2]=A.a[3][2]=1;
        //A.a[3][3]=a;A=qpow(A,q-1);
        //sum=(A.a[2][1]+a*A.a[3][1]%mod)%mod;
        ll s=qpow((1+mod-a)%mod,mod-2);
        sum=q-1-a*(1-qpow(a,q-1))%mod*s%mod;
        sum=(sum%mod+mod)%mod;
        sum=sum*s%mod;
        E=(E+sum*p%mod*p%mod)%mod;
    }
    ans=ans*E%mod;
    printf("%lld\n",ans);
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值