718C - A - Sasha and Array
设
f
⃗
(
n
)
=
(
f
(
n
+
1
)
,
f
(
n
)
)
T
\vec f(n)=(f(n+1),f(n))^T
f(n)=(f(n+1),f(n))T,那么
f
⃗
(
n
)
=
A
n
f
⃗
(
0
)
\vec f(n)=A^n\vec f (0)
f(n)=Anf(0)
由于
f
⃗
(
0
)
=
(
1
,
0
)
T
\vec f(0)=(1,0)^T
f(0)=(1,0)T,所以
f
(
n
)
=
A
n
(
2
;
1
)
f(n)=A^n(2;1)
f(n)=An(2;1).因为我们将其转化为了乘积关系,所以用线段树维护即可.
#include <cstdio>
#include <cstring>
typedef long long Matrixtype;
const int N=100000+5;
const int Dim=3;
const Matrixtype mod=1e9+7;
struct Matrix{
Matrixtype a[Dim][Dim];
inline Matrixtype* const operator[](const int _i){return a[_i];}
void setsiz(int siz){a[0][0]=siz;}
void empty(int siz=0){
if(siz){a[0][0]=siz;for(int i=a[0][0];i;i--)for(int j=a[0][0];j;j--)a[i][j]=0;}
else memset(a,0,sizeof(a));
}
void I(int siz){a[0][0]=siz;for(int i=siz;i;i--)for(int j=siz;j;j--)a[i][j]=(i==j);}
void J(int siz){a[0][0]=siz;for(int i=siz;i;i--)for(int j=siz;j;j--)a[i][j]=1;}
void copy(Matrix &b){
a[0][0]=b[0][0];
for(int i=a[0][0];i;i--){
for(int j=a[0][0];j;j--)a[i][j]=b[i][j];
}
}
void prt(){
puts("--------------");
for(int i=1;i<=a[0][0];i++,puts("")){
for(int j=1;j<=a[0][0];j++)
//printf("%d ",a[i][j]);
printf("%I64d ",a[i][j]);
}
}
Matrix operator*(Matrix &b)const{
Matrix res;
res[0][0]=a[0][0];
for(int i=a[0][0];i;i--){
for(int j=a[0][0];j;j--){
res[i][j]=0;
for(int k=a[0][0];k;k--){
res[i][j]+=a[i][k]*b[k][j];
res[i][j]%=mod;
}
}
}
// for(int i=a[0][0];i;i--){
// for(int j=a[0][0];j;j--){
// res[i][j]%=mod;
// }
// }
return res;
}
Matrix operator+(Matrix &b)const{
Matrix res;res[0][0]=a[0][0];
for(int i=1;i<=a[0][0];i++){
for(int j=1;j<=a[0][0];j++){
res[i][j]=(a[i][j]+b[i][j])%mod;
}
}
return res;
}
void pow(Matrixtype n,Matrix &res){
Matrix x;
res.I(a[0][0]);
x.copy(*this);
while(n){
if(n&1)res=res*x;
x=x*x; n>>=1;
}
}
}X,Y,mul[N<<2],sgt[N<<2];
long long a[N];
bool nid[N<<2];
void pushup(int p){
sgt[p]=sgt[p<<1]+sgt[p<<1|1];
}
void pushdown(int p){
if(nid[p]){
sgt[p<<1]=sgt[p<<1]*mul[p];
sgt[p<<1|1]=sgt[p<<1|1]*mul[p];
mul[p<<1 ]=mul[p<<1 ]*mul[p];
mul[p<<1|1]=mul[p<<1|1]*mul[p];
nid[p<<1 ]=1;
nid[p<<1|1]=1;
mul[p].I(2);
nid[p]=0;
}
}
void build(int p,int l,int r){
mul[p].I(2);
if(l==r){
X.pow(a[l],sgt[p]);
return ;
}
int m=(l+r)>>1;
build(p<<1,l,m);build(p<<1|1,m+1,r);
pushup(p);
}
void update(int p,int l,int r,int L,int R,Matrix &X){
if(L<=l&&r<=R){
sgt[p]=sgt[p]*X;
mul[p]=mul[p]*X;nid[p]=1;
return ;
}
pushdown(p); int m=(l+r)>>1;
if(L<=m)update(p<<1 ,l ,m,L,R,X);
if(m< R)update(p<<1|1,m+1,r,L,R,X);
pushup(p);
}
long long query(int p,int l,int r,int L,int R){
if(L<=l&&r<=R){
return sgt[p][2][1];
}
pushdown(p); int m=(l+r)>>1;
if(R<=m)return query(p<<1 ,l ,m,L,R);
if(m< L)return query(p<<1|1,m+1,r,L,R);
return (query(p<<1,l,m,L,R)+query(p<<1|1,m+1,r,L,R))%mod;
}
long long res[N];int rtop=0;
void prt(long long c){res[++rtop]=c;}
int main(){
X.empty(2);
X[1][1]=1;X[1][2]=1;
X[2][1]=1;X[2][2]=0;
int n,m;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)scanf("%I64d",&a[i]);
build(1,1,n);
while(m--){
int o,l,r;
scanf("%d%d%d",&o,&l,&r);
if(o==1){
long long x;
scanf("%I64d",&x);
X.pow(x,Y);
update(1,1,n,l,r,Y);
}
else{
prt(query(1,1,n,l,r));
}
//for(int i=1;i<=n;i++){printf("(%I64d)",query(1,1,n,i,i));}
}
for(int i=1;i<=rtop;i++)printf("%I64d\n",res[i]);
}
618E - C - Wet Shark and Blocks
设
d
p
⃗
x
×
1
(
i
)
\vec{dp}_{x\times 1}(i)
dpx×1(i)是
i
i
i长度数字的方案数,根据:
d
p
(
i
)
[
(
j
⋅
10
+
k
)
%
x
]
=
d
p
(
i
−
1
)
[
j
]
⋅
f
a
c
[
k
]
dp(i)[(j\cdot 10+k)\%x]=dp(i-1)[j]\cdot \mathrm{fac}[k]
dp(i)[(j⋅10+k)%x]=dp(i−1)[j]⋅fac[k]
得到
d
p
⃗
(
i
)
=
A
d
p
⃗
(
i
−
1
)
\vec{dp}(i)=A\vec{dp}(i-1)
dp(i)=Adp(i−1).转移即可.
还可以根据
1
0
k
10^k
10k最多
x
x
x个不同的取值转移,但是太过麻烦我写烂了…
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long Matrixtype;
const int Dim=101;
const Matrixtype mod=1e9+7;
struct Matrix{
Matrixtype a[Dim][Dim];
inline Matrixtype* const operator[](const int _i){return a[_i];}
void setsiz(int siz){a[0][0]=siz;}
void empty(int siz=0){
if(siz){a[0][0]=siz;for(int i=a[0][0];i;i--)for(int j=a[0][0];j;j--)a[i][j]=0;}
else memset(a,0,sizeof(a));
}
void I(int siz){a[0][0]=siz;for(int i=siz;i;i--)for(int j=siz;j;j--)a[i][j]=(i==j);}
void J(int siz){a[0][0]=siz;for(int i=siz;i;i--)for(int j=siz;j;j--)a[i][j]=1;}
void copy(Matrix &b){
a[0][0]=b[0][0];
for(int i=a[0][0];i;i--){
for(int j=a[0][0];j;j--)a[i][j]=b[i][j];
}
}
void prt(){
puts("--------------");
for(int i=1;i<=a[0][0];i++,puts("")){
for(int j=1;j<=a[0][0];j++)
//printf("%d ",a[i][j]);
printf("%I64d ",a[i][j]);
}
}
Matrix operator*(Matrix &b)const{
Matrix res;
res[0][0]=a[0][0];
for(int i=a[0][0];i;i--){
for(int j=a[0][0];j;j--){
res[i][j]=0;
for(int k=a[0][0];k;k--){
res[i][j]+=a[i][k]*b[k][j];
res[i][j]%=mod;
}
}
}
// for(int i=a[0][0];i;i--){
// for(int j=a[0][0];j;j--){
// res[i][j]%=mod;
// }
// }
return res;
}
void pow(Matrixtype n,Matrix &res){
Matrix x;
res.I(a[0][0]);
x.copy(*this);
while(n){
if(n&1)res=res*x;
x=x*x; n>>=1;
}
}
};
Matrix X[(sizeof(Matrixtype)<<2)+1],tr,ans;
void premat(Matrixtype n,Matrix &Mat){
int k=1;X[0].copy(Mat);
while(n>>k){
X[k]=X[k-1]*X[k-1];k++;
}
}
void prepow(Matrixtype n,Matrix &res){
res.I(X[0][0][0]);
for(int bit=0;n>>bit;bit++){
if((n>>bit)&1)res=res*X[bit];
}
}
long long qp(long long a,long long b){
long long res=1;
while(b){
if(b&1)res=res*a%mod;
a=a*a%mod;b>>=1;
}
return res;
}
long long ten[200];
long long fac[200];
int main(){
int n,k,x;long long b;
scanf("%d%I64d%d%d",&n,&b,&k,&x);
for(int i=1;i<=n;i++){
int t;
scanf("%d",&t);
fac[t]++;
}
for(int i=x;i<=10;i++)fac[i%x]+=fac[i];
tr.empty(x);
for(int i=0;i<x;i++){
for(int j=0;j<x;j++)tr[(i*10+j)%x+1][i+1]+=fac[j];
}
premat(b,tr);prepow(b,ans);
printf("%I64d\n",ans[k+1][1]);
}
325E - F - The Red Button
很容易发现奇数情况是不行的,再证明偶数情况:
我们设
G
G
G是标号图.
对于任意
i
i
i,有
i
/
2
i/2
i/2和
(
i
+
N
)
/
2
(i+N)/2
(i+N)/2指向它.同时它的出度为
2
2
2.
所以
G
G
G是
2
2
2-正则图.下面有三个定理:
定理1 任意
d
d
d-正则图是线图.
定理2
L
(
G
)
L(G)
L(G)是
2
d
−
2
2d-2
2d−2-正则图当且仅当
G
G
G是
d
d
d-正则图.
定理3
G
G
G是欧拉图当且仅当
L
(
G
)
L(G)
L(G)是哈密顿图.
我大致已经证了求线图的原图也即
L
−
1
(
G
)
L^{-1}(G)
L−1(G)是
N
P
\mathrm{NP}
NP-
h
a
r
d
hard
hard问题.但并不妨碍做题.
根据定理
1
1
1我们知道
G
G
G是线图,也就是存在
L
−
1
(
G
)
L^{-1}(G)
L−1(G).根据定理
2
2
2知道
L
−
1
(
G
)
L^{-1}(G)
L−1(G)是
2
2
2-正则图,所以
L
−
1
(
G
)
L^{-1}(G)
L−1(G)有欧拉回路,对应
G
G
G的一个哈密顿回路。因为是
2
−
2-
2−正则图.所以随意走动我们都能得到一个欧拉路(根据某个忘记名字的算法,我们在
2
2
2-正则图上一直走割边所以有一个欧拉路)…
#include <cstdio>
#include <cstring>
const int N=1e5+5;
bool vis[N];int n,res[N],rtop=0;
void dfs(int u){
if(vis[u])return ;
vis[u]=1;
dfs((u<<1)%n);dfs((u<<1|1)%n);
res[++rtop]=u;
}
int main(){
scanf("%d",&n);
if(n&1){
puts("-1");
return 0;
}
dfs(0);
while(rtop)printf("%d ",res[rtop--]);
printf("0\n");
}
717E - G - Paint it really, really dark gray
dfs搜索即可,别犯智障错误就行orz
#include <cstdio>
#include <cstring>
const int N=2e5+5,M=N*2;
const int Headsize=N,Edgesize=M;
int head[Headsize+5],mal;
struct edge{
int nx,to;
}e[Edgesize+5];
inline void init(){
mal=1;
memset(head,0,sizeof(head));
}
inline void addedge(int u,int v){
e[mal].to=v;e[mal].nx=head[u];head[u]=mal++;
}
int col[N],has[N];
void dfs(int u,int f){
has[u]=col[u];
for(int i=head[u];i;i=e[i].nx){
int v=e[i].to;
if(v==f)continue;
dfs(v,u);
has[u]|=has[v];
}
}
void ptr(int u,int f){
printf("%d ",u);col[u]^=1;
for(int i=head[u];i;i=e[i].nx){
int v=e[i].to;
if(v==f)continue;
if(has[v]){
ptr(v,u);
printf("%d ",u);col[u]^=1;
}
}
if(col[u]){
if(f){
printf("%d %d ",f,u);col[f]^=1;col[u]^=1;
}else{
//puts("here");
printf("%d %d %d",e[head[u]].to,u,e[head[u]].to);
}
}
}
int main(){
int n;
scanf("%d",&n);
init();
for(int i=1;i<=n;i++){
int t;
scanf("%d",&t);
if(t==1)col[i]=0;else col[i]=1;
}
for(int i=1;i<n;i++){
int u,v;
scanf("%d%d",&u,&v);
addedge(u,v);
addedge(v,u);
}
dfs(1,0);
if(!has[1]){
//puts("here");
puts("1");
}else{
printf("%d %d %d %d ",1,e[head[1]].to,1,e[head[1]].to);
col[1]^=1;
ptr(1,0);
}
}
623B - H - Array GCD
根据我写的错解可以发现
p
r
e
pre
pre之间有覆盖关系,
s
u
f
suf
suf也是.
先求
p
r
e
pre
pre的素因子
s
s
s可以覆盖所有方案,再用同样的方法转移
s
u
f
suf
suf.
我们显然有:
r
e
s
=
min
i
,
j
,
s
{
p
r
e
[
i
]
[
s
]
+
s
u
f
[
j
]
[
s
]
+
(
j
−
1
−
i
)
a
}
res=\min_{i,j,s}\{pre[i][s]+suf[j][s]+(j-1-i)a\}
res=i,j,smin{pre[i][s]+suf[j][s]+(j−1−i)a}
r
e
s
i
=
min
s
{
p
r
e
i
+
min
j
{
(
s
u
f
j
+
j
a
)
}
}
−
(
i
+
1
)
a
.
res_i=\min_{s}\{pre_i+\min_{j}\{(suf_j+ja)\}\}-(i+1)a.
resi=smin{prei+jmin{(sufj+ja)}}−(i+1)a.
暴力转移即可…
#include <cstdio>
#include <map>
#include <cmath>
#include <cstring>
#include <utility>
using namespace std;
const int N=1e6+5;
long long pre[N][32],suf[2][32],gor[32];int q=0,prim[32],qq=0,pp[32];
int gcd(int a,int b){
int r;
while(b){r=a%b;a=b;b=r;}
return a;
}
int n;
void Ins(int x,long long b,long long *val,int &q,int *prim){
int sqrtx=(int)sqrt(x+1);
for(int i=2;i<=sqrtx;i++){
if(x%i==0){
x/=i;
while(x%i==0)x/=i;
bool f=1;
for(int j=1;j<=q;j++)if(prim[j]==i){val[j]=min(val[j],b),f=0;break;}
if(f){prim[++q]=i;
val[q]=b;
}}
}
if(x>1){
bool f=1;
for(int j=1;j<=q;j++)if(prim[j]==x){val[j]=min(val[j],b),f=0;break;}
if(f){prim[++q]=x;
val[q]=b;}
}
}
long long x[N],res=0x7fffffffffffffffLL;
pair<int,int> incheck[1000];
int main(){
long long a,b;
memset(pre,0x3f,sizeof(pre));
memset(suf,0x3f,sizeof(suf));
scanf("%d%I64d%I64d",&n,&a,&b);
for(int i=1;i<=n;i++)scanf("%I64d",&x[i]);
res=(n-1)*a;
// if(x[1]-1>1)pre[1][x[1]-1]=b;
// pre[1][x[1]]=0;pre[1][x[1]+1]=b;
// int y;
// for(int i=2;i<=n;i++){
// for(auto c:pre[i-1]){
// y=gcd(c.first,x[i]-1);
// if(y>1){
// if(pre[i].count(y))pre[i][y]=min(pre[i][y],c.second+b);else pre[i][y]=c.second+b;
// res=min(pre[i][y]+(n-i)*a,res);
// }
// y=gcd(c.first,x[i]);
// if(y>1){
// if(pre[i].count(y))pre[i][y]=min(pre[i][y],c.second);else pre[i][y]=c.second;
// res=min(pre[i][y]+(n-i)*a,res);
// }
// y=gcd(c.first,x[i]+1);
// if(y>1){
// if(pre[i].count(y))pre[i][y]=min(pre[i][y],c.second+b);else pre[i][y]=c.second+b;
// res=min(pre[i][y]+(n-i)*a,res);
// }
// }
// }
// for(int i=1;i<=n;i++){
// printf("%d:\n",i);
// for(auto c:pre[i]){
// printf("(%d,%I64d)",c.first,c.second);
// }
// puts("");
// }
// if(x[n]-1>1)suf[n][x[n]-1]=b;
// suf[n][x[n]]=0;suf[n][x[n]+1]=b;
// for(int i=n-1;i;i--){
// for(auto c:suf[i+1]){
// y=gcd(c.first,x[i]-1);
// if(y>1){
// if(suf[i].count(y))
// suf[i][y]=min(suf[i][y],c.second+b);else suf[i][y]=c.second+b;
// res=min(suf[i][y]+(i-1)*a,res);
// }
// y=gcd(c.first,x[i]);
// if(y>1){
// if(suf[i].count(y))
// suf[i][y]=min(suf[i][y],c.second);else suf[i][y]=c.second;
// res=min(suf[i][y]+(i-1)*a,res);
// }
// y=gcd(c.first,x[i]+1);
// if(y>1){
// if(suf[i].count(y))
// suf[i][y]=min(suf[i][y],c.second+b);else suf[i][y]=c.second+b;
// res=min(suf[i][y]+(i-1)*a,res);
// }
// }
// }
// puts("");
// for(int i=n;i>=1;i--){
// printf("%d:\n",i);
// for(auto c:suf[i]){
// printf("(%d,%I64d)",c.first,c.second);
// }
// puts("");
// }
// for(auto c:pre[n]){
// res=min(res,c.second);
// gor[c.first]=c.second+n*a;
// }
Ins(x[1]-1,b,pre[1],q,prim);
Ins(x[1],0,pre[1],q,prim);
Ins(x[1]+1,b,pre[1],q,prim);
// for(int i=1;i<=q;i++){
// printf("[%I64d,%d]",pre[1][i],prim[i]);
// }
// puts("");
// printf("%I64d\n",res);
for(int i=2;i<=n;i++){
for(int j=1;j<=q;j++){
if(x[i]%prim[j]==0){
pre[i][j]=min(pre[i][j],pre[i-1][j]);res=min(res,pre[i][j]+(n-i)*a);
}
if((x[i]+1)%prim[j]==0){
pre[i][j]=min(pre[i][j],pre[i-1][j]+b);res=min(res,pre[i][j]+(n-i)*a);
}
if((x[i]-1)%prim[j]==0){
pre[i][j]=min(pre[i][j],pre[i-1][j]+b);res=min(res,pre[i][j]+(n-i)*a);
}
}
// printf("----------\n%d:\n",i);
// for(int j=1;j<=q;j++){
// printf("[%I64d,%d]",pre[i][j],prim[j]);
// }
// puts("");
// printf("rres%I64d\n",res);
}
Ins(x[n]-1,0,suf[0],qq,pp);
Ins(x[n],0,suf[0],qq,pp);
Ins(x[n]+1,0,suf[0],qq,pp);
// for(int i=1;i<=qq;i++){
// printf("[%I64d,%d]",suf[0][i],pp[i]);
// }
// puts("");
int g=0;
for(int i=1;i<=q;i++){
for(int j=1;j<=qq;j++){
if(prim[i]==pp[j])incheck[++g]={i,j};
}
}
int qwq=0;
memset(gor,0x3f,sizeof(gor));
//printf("%I64d\n",res);
for(int i=n-1,j=n;j!=0;i--,j--){
qwq^=1;
memset(suf[qwq],0x3f,sizeof(suf[qwq]));
for(int s=1;s<=qq;s++){
if((x[j]-1)%pp[s]==0){
suf[qwq][s]=min(suf[qwq][s],suf[qwq^1][s]+b);
res=min(res,suf[qwq][s]+i*a);
}
if((x[j])%pp[s]==0){
suf[qwq][s]=min(suf[qwq][s],suf[qwq^1][s]);
res=min(res,suf[qwq][s]+i*a);
}
if((x[j]+1)%pp[s]==0){
suf[qwq][s]=min(suf[qwq][s],suf[qwq^1][s]+b);
res=min(res,suf[qwq][s]+i*a);
}
}
// printf("---------\n%d:\n",j);
// for(int k=1;k<=qq;k++){
// printf("[%d,%I64d]",pp[k],suf[qwq][k]);
// }
// puts("");
// printf("%I64d\n",res);
if(i)for(int s=1;s<=qq;s++)gor[s]=min(suf[qwq][s]+j*a,gor[s]);
// for(int s=1;s<=qq;s++){
// if(gor.count(prim[s])){
// gor[prim[s]]=min(suf[qwq][s]+j*a,gor[prim[s]]);
// }else {
// for(int k=-1;k<=1;k++){
// if(gcd(t.first,prim[s])>1){gor[prim[s]]=suf[qwq][s]+j*a;break;}
// }
// }
// }
// for(int k=1;k<=q;k++){
// for(int s=1;s<=qq;s++){
// if(prim[k]==pp[s]){
if(i)for(int k=1;k<=g;k++)res=min(res,pre[i][incheck[k].first]+gor[incheck[k].second]-j*a);
// }
// }
// }
}
printf("%I64d\n",res);
}