题目
3802,3803,3804.
失分小结
估分
70+80+30=180 (小C说这是基础分)
实际分数
70+90+10=170
T2只要加上前缀和优化就AC了啊啊啊啊啊
当然T3不小心炸了
题解
T1
P70
杨辉三角
CODE
#include<cstdio>
#define N 1005
#define P 1000000007
int a,b,n;
bool check(int x) {
while(x) {
int t=x%10;
if(t!=a&&t!=b)return 0;
x/=10;
}
return 1;
}
int main() {
scanf("%d %d %d",&a,&b,&n);
int C[N][N];
C[0][0]=C[1][0]=C[1][1]=1;
for(int i=2; i<=n; i++) {
C[i][0]=C[i][i]=1;
for(int j=1; j<i; j++)
C[i][j]=(C[i-1][j]+C[i-1][j-1])%P;
}
int ans=0;
for(int i=0; i<=n; i++)
if(check(a*i+b*(n-i)))
ans=(ans+C[n][i])%P;
printf("%d",ans);
return 0;
}
P100
正解乘法逆元:
CODE
#include<cstdio>
#define P 1000000007
using namespace std;
int a,b,n;
bool check(int x) {
while(x) {
int t=x%10;
if(t!=a&&t!=b)return 0;
x/=10;
}
return 1;
}
int fast(int x,int p) {
int res=1;
while(p) {
if(p&1)res=1ll*res*x%P;
x=1ll*x*x%P;
p>>=1;
}
return res;
}
int main() {
scanf("%d %d %d",&a,&b,&n);
int ans=0,c=1;
for(int i=0; i<=n; i++) {
if(check(i*a+(n-i)*b))ans=(ans+c)%P;
c=1ll*c*(n-i)%P*fast(i+1,P-2)%P;
}
printf("%d\n",ans);
return 0;
}
T2
P90
定义
我也不知道为什么
CODE
#include<cstdio>
#include<iostream>
#define N 3005
#define P 1000000007
using namespace std;
char a[N];
int dp[N][N];
int n;
int ans=0;
bool check(int st1,int st2) {
int ed1=st2-1;
for(; st1<=ed1; st1++,st2++) {
if(a[st1]>a[st2])return 0;
if(a[st2]>a[st1])return 1;
}
return 0;
}
int main() {
scanf("%d",&n);
scanf("%s",a+1);
for(int i=1; i<=n; i++) {
for(int j=1; j<i; j++) {
if(a[i-j+1]!='0') {
for(int k=1; k<j; k++) {
dp[i][j]=(dp[i][j]+dp[i-j][k])%P;
}
if(check(i-j-j+1,i-j+1))
dp[i][j]=(dp[i][j]+dp[i-j][j])%P;
}
}
dp[i][i]=1;
}
int ans=0;
for(int i=1; i<=n; i++)ans=(ans+dp[n][i])%P;
printf("%d",ans);
return 0;
}
P95
网站上95本地100.
前缀和优化…
CODE
#include<cstdio>
#include<iostream>
#define N 3005
#define P 1000000007
using namespace std;
char a[N];
int dp[N][N];
int n;
int ans=0;
bool check(int st1,int st2) {
int ed1=st2-1;
for(; st1<=ed1; st1++,st2++) {
if(a[st1]>a[st2])return 0;
if(a[st2]>a[st1])return 1;
}
return 0;
}
int main() {
scanf("%d",&n);
scanf("%s",a+1);
for(int i=1; i<=n; i++) {
for(int j=1; j<i; j++) {
if(a[i-j+1]!='0') {
dp[i][j]=dp[i-1][j-1];
if(!check(i-j-j+2,i-j+1))
dp[i][j]=(dp[i][j]+dp[i-j][j-1])%P;
if(check(i-j-j+1,i-j+1))
dp[i][j]=(dp[i][j]+dp[i-j][j])%P;
}
}
dp[i][i]=1;
}
int ans=0;
for(int i=1; i<=n; i++)
ans=(ans+dp[n][i])%P;
printf("%d",ans);
return 0;
}
P100
CODE
#include<cstdio>
#include<iostream>
#define N 3005
#define P 1000000007
#define "register" is nonexistent
using namespace std;
char a[N];
int dp[N][N],lcp[N][N];
int n;
bool check(int st1,int st2) {
int ed1=st2-1;
int len=lcp[st2][st1];
if(len+st1>ed1)return 0;
return a[st1+len]<a[st2+len];
}
int main() {
scanf("%d",&n);
scanf("%s",a+1);
for(int i=n; i>=1; i--)
for(int j=i; j>=1; j--)
if(a[i]==a[j])lcp[i][j]=lcp[i+1][j+1]+1;
else lcp[i][j]=0;
for(int i=1; i<=n; i++) {
for(int j=1; j<i; j++) {
if(a[i-j+1]!='0') {
dp[i][j]=dp[i-1][j-1];
if(!check(i-j-j+2,i-j+1))
dp[i][j]=(dp[i][j]+dp[i-j][j-1])%P;
if(check(i-j-j+1,i-j+1))
dp[i][j]=(dp[i][j]+dp[i-j][j])%P;
}
}
dp[i][i]=1;
}
int ans=0;
for(int i=1; i<=n; i++)
ans=(ans+dp[n][i])%P;
printf("%d",ans);
return 0;
}
T3
P100
CODE
引用自Komachi大佬.
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
#define REP(i,a,b) for(int i=(a),i##_END_=(b);i<i##_END_;i++)
inline void Max(int &x,int y) {if(x<y)x=y;}
void Rd(int &x) {
x=0;char c;
while(c=getchar(),c<48);
do x=(x<<3)+(x<<1)+(c&15);
while(c=getchar(),c>47);
}
#define M 100004
#define K 20
#define INF 0x3f3f3f3f
int n,m;
#define LREP(i,A) for(int i=Head[A];i;i=Next[i])
int Next[M<<1],V[M<<1],Head[M],tot;
void addedge(int u,int v) {Next[++tot]=Head[u],V[Head[u]=tot]=v;}
int Dis[M],Fa[M],LT,RT;
void Find(int A,int f,int &t) {
Dis[A]=Dis[f]+1;
Fa[A]=f;
if(Dis[A]>Dis[t])t=A;
int B;
LREP(i,A)if((B=V[i])!=f)
Find(B,A,t);
}
bool Use[M];
int Mx[M],Dep[M],Fr[M];
int RMQ1[M][K],RMQ2[M][K];
int Query(int a,int b,int RMQ[M][K]) {
if(a>b)return -INF;
int k=31-__builtin_clz(b-a+1);
return max(RMQ[a][k],RMQ[b-(1<<k)+1][k]);
}
void FindMx(int A,int f,int fr) {
int B;
Fr[A]=fr;
Dep[A]=Dep[f]+1;
Max(Mx[fr],Dep[A]);
LREP(i,A)if((B=V[i])!=f&&!Use[B])
FindMx(B,A,fr);
}
int main() {
Rd(n);
REP(i,1,n) {
int u,v;
Rd(u),Rd(v);
addedge(u,v);
addedge(v,u);
}
Rd(m);
LT=RT=0;
Dis[0]=Dep[0]=-1;
Find(1,0,LT);
Find(LT,0,RT);
int p=RT;
while(p) {
Use[p]=1;
p=Fa[p];
}
p=RT;
while(p) {
FindMx(p,0,p);
RMQ1[Dis[p]][0]=Dis[p]+Mx[p];
RMQ2[Dis[p]][0]=Mx[p]-Dis[p];
p=Fa[p];
}
REP(k,1,K)REP(i,0,Dis[RT]+1) {
int j=i+(1<<k-1);
if(j>Dis[RT])break;
RMQ1[i][k]=max(RMQ1[i][k-1],RMQ1[j][k-1]);
RMQ2[i][k]=max(RMQ2[i][k-1],RMQ2[j][k-1]);
}
while(m--) {
int x,y,u,v,Ans=0;
Rd(x),Rd(y);
u=Fr[x],v=Fr[y];
if(Dis[u]>Dis[v])swap(u,v),swap(x,y);
Ans=max(min(Dep[x]+Dis[u],Dep[y]+Dis[v]),min(Dep[y]+Dis[RT]-Dis[v],Dep[x]+Dis[RT]-Dis[u]));
int pos=Dep[y]-Dep[x]+Dis[u]+Dis[v]>>1;
Max(Ans,Query(Dis[u]+1,min(Dis[v]-1,pos),RMQ1)-Dis[u]+Dep[x]);
Max(Ans,Query(max(Dis[u],pos)+1,Dis[v]-1,RMQ2)+Dis[v]+Dep[y]);
printf("%d\n",Ans);
}
return 0;
}