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+k∗m2modm
Meanwhile,
k
∗
m
2
m
m
o
d
m
=
0
\frac{k*m^2}{m}\bmod m=0
mk∗m2modm=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
i→pi→ppi→...→i。如果环长度只有
1
1
1,略过。
只要环中有一个
b
p
i
≥
a
i
b_{p_i}\ge a_i
bpi≥ai的,答案就是
−
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=1∑k[⌊D(A−1+B∗i)⌋=⌊D(A+C∗i)⌋],当
k
>
⌊
D
−
2
C
−
B
⌋
k>\lfloor\frac{D-2}{C-B}\rfloor
k>⌊C−BD−2⌋两边一定不相等,因为它们直接的距离相差大于等于
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(A−1+B∗i)⌋≤⌊D(A+C∗i)⌋,且当
k
≤
⌊
D
−
2
C
−
B
⌋
k\le\lfloor\frac{D-2}{C-B}\rfloor
k≤⌊C−BD−2⌋,他们的差最多为
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=1∑k⌊D(A+C∗i)⌋−⌊D(A−1+B∗i)⌋。
这是类欧几里得算法模板。
#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∗(n−i+1)∗2,只需解决以下问题即可:
给定两个数
x
,
s
u
m
i
x,sum_i
x,sumi初始都为
0
0
0,随机进行
q
q
q次操作,每次操作:
- 有 1 − P i 1-P_i 1−Pi概率什么都不做
- 有 P i ∗ 1 2 ∗ m + 1 P_i*\frac{1}{2*m+1} Pi∗2∗m+11的概率使得 s u m i = s u m i + x sum_i=sum_i+x sumi=sumi+x
- 有 P i ∗ 1 2 ∗ m + 1 P_i*\frac{1}{2*m+1} Pi∗2∗m+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,...,m−1})
- 有 P i ∗ 1 2 ∗ m + 1 P_i*\frac{1}{2*m+1} Pi∗2∗m+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,...,m−1})
求
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
x≥v的概率。则
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=0∑q−1v=0∑m−1pj,v∗v∗Pi∗2∗m+11=j=0∑q−1v=1∑m−1pj,≥v∗Pi∗2∗m+11pj+1,≥v=pj,≥v∗(1−Pi)+Pi∗pj,≥v∗2∗m+1m+1+m−v+Pi∗(1−pj,≥v)∗2∗m+1m−v=pj,≥v∗(1−2∗m+1m∗Pi)+Pi∗2∗m+1m−v
令
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=1−2∗m+1m∗Pi,bv=2∗m+1m−v,可以得到
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(v≥1)pj+1,≥v=pj,≥v∗ai+Pi∗bv
观察该式子可以发现
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=Pi∗bv∗k=0∑j−1aij(j≥1)。
则可以得到
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=1∑nsumi=i=1∑nv=1∑m−1j=1∑q−1∗Pi∗2∗m+11Pi∗bv∗k=0∑j−1aij=2∗m+11∗(v=1∑m−1bv)∗i=1∑nPi2(j=1∑q−1k=0∑j−1aij)
对
(
∑
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=1q−1∑k=0j−1aij)可以设计矩阵快速幂
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=1∑q−1k=0∑j−1aij)=1−aiq−1−1−aiai(1−aiq−1)
从而整个过程只需要枚举
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)∗(2∗m+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);
}