AtCoder Beginner Contest 208
A
没什么好说的,就是模拟。
code:
#include<bits/stdc++.h>
#define I inline
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define abs(x) ((x)>0?(x):-(x))
#define re register
#define ll long long
#define db double
#define N 300000
#define M 200000
#define mod 998244353
#define eps (1e-7)
#define U unsigned int
#define IT set<ques>::iterator
#define Gc() getchar()
#define Me(x,y) memset(x,y,sizeof(x))
using namespace std;
int n,m,k,x,y,z;
int main(){
scanf("%d%d",&x,&y);printf("%s\n",(y>=x)&&(y<=6*x)?("Yes"):("No"));
}
B
从后往前贪心即可。
code:
#include<bits/stdc++.h>
#define I inline
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define abs(x) ((x)>0?(x):-(x))
#define re register
#define ll long long
#define db double
#define N 300000
#define M 200000
#define mod 998244353
#define eps (1e-7)
#define U unsigned int
#define IT set<ques>::iterator
#define Gc() getchar()
#define Me(x,y) memset(x,y,sizeof(x))
using namespace std;
int n,p,ans=3628800,tot;
int main(){
re int i;scanf("%d",&n);for(i=10;i;i--) tot+=n/ans,n%=ans,ans/=i;printf("%d\n",tot);
}
C
首先平均分到不能再分,然后排个序分即可。
code:
#include<bits/stdc++.h>
#define I inline
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define abs(x) ((x)>0?(x):-(x))
#define re register
#define ll long long
#define db double
#define N 300000
#define M 200000
#define mod 998244353
#define eps (1e-7)
#define U unsigned int
#define IT set<ques>::iterator
#define Gc() getchar()
#define Me(x,y) memset(x,y,sizeof(x))
using namespace std;
int n,tot,pus;ll m,k,ans[N+5];
struct yyy{int A,id;}F[N+5];
I bool cmp(yyy x,yyy y){return x.A<y.A;}
int main(){
freopen("1.in","r",stdin);
re int i;scanf("%d%lld",&n,&k);for(i=1;i<=n;i++)scanf("%d",&F[i].A),F[i].id=i;sort(F+1,F+n+1,cmp);
ans[1]=k/n;for(i=2;i<=n;i++) ans[i]=ans[i-1];k%=n;
for(i=1;i<=k;i++) ans[F[i].id]++;for(i=1;i<=n;i++) printf("%lld\n",ans[i]);
}
D
似乎是一个常见套路,拿来出题真不要脸。
考虑floyd的本质就是每次允许一个点转移然后枚举每一对点对看能否更新答案。
按照这个计算答案即可。时间复杂度\(O(n^3)\)
code:
#include<bits/stdc++.h>
#define I inline
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define abs(x) ((x)>0?(x):-(x))
#define re register
#define ll long long
#define db double
#define N 400
#define M 200000
#define mod 998244353
#define eps (1e-7)
#define U unsigned int
#define IT set<ques>::iterator
#define Gc() getchar()
#define Me(x,y) memset(x,y,sizeof(x))
using namespace std;
int n,m,x,y,z;ll ans,F[N+5][N+5];
int main(){
freopen("1.in","r",stdin);
re int i,j,k;scanf("%d%d",&n,&m);Me(F,0x3f);for(i=1;i<=m;i++) scanf("%d%d%d",&x,&y,&z),F[x][y]=z;for(i=1;i<=n;i++) F[i][i]=0;
for(k=1;k<=n;k++){
for(i=1;i<=n;i++){
for(j=1;j<=n;j++) F[i][j]=min(F[i][j],F[i][k]+F[k][j]),ans+=(F[i][j]>1e17?0:F[i][j]);
}
}printf("%lld\n",ans);
}
E
狂肝这道题居然1h10min没肝出来。然后发现自己和std做法不一样。
在这个数据上应该是完全吊打std的,但是不知道为什么跑得很慢。
首先显然有数位dp:设\(f_{i,j,k}\)表示到了第\(i\)位,当前选了\(j\),总乘积为\(k\)
然而这个是\(10lognk\)的不可能过去。
其实有些数是不可能被乘出来的,比如一些质数。
针对这个问题,std是直接存\(2\),\(3\),\(5\),\(7\)的个数,以这个为下标来dp,这个复杂度是\(O(10lognlog^4k)\)很不优。
考虑到最终乘积\(w\leq k\)即\(\frac{k}{w}\geq 1\),这里\(0\)特殊处理一下。
我们就可以在状态里存\(\lfloor\frac{k}{w}\rfloor\),这个根据整除分块那套理论是\(O(\sqrt k)\)个不同的数。
所以最后复杂度是\(O(10logn\sqrt k)\)
\(\sqrt k=31622\),\(log^4k=810000\)远大于这个。
code:
#include<bits/stdc++.h>
#define I inline
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define abs(x) ((x)>0?(x):-(x))
#define re register
#define ll long long
#define db double
#define N 80000
#define M 200000
#define mod 998244353
#define eps (1e-7)
#define U unsigned int
#define IT set<ques>::iterator
#define Gc() getchar()
#define Me(x,y) memset(x,y,sizeof(x))
using namespace std;
int k,m,cnt,A[N+5];ll n,now,pus,tot,F[20][10][N+5],H[20][N+5];map<int,int> G;
I ll find(int x,int w,int flag,ll po){
re int i,j,h,now=(n/po)%10;ll ans=0;if(!x) return flag&&(w);
if(flag){
ans+=find(x-1,(!now||w==cnt+1)?cnt+1:G[A[w]/(now)],1,po/10);ans+=find(x-1,w,0,po/10);
for(i=(x==m);i<now;i++) {
for(h=1;h<=cnt;h++) k/A[h]<=A[w]&&(ans+=F[x][i][h]);ans+=F[x][i][cnt+1];
(w==cnt+1)&&(ans+=F[x][i][0]);//printf("%lld %d\n",ans,A[w]);
}//printf("%lld %d\n\n",ans,x);
return ans;
}
for(i=1;i<=9;i++){
for(h=1;h<=cnt+1;h++) ans+=F[x][i][h];
} /*printf("%lld %d\n",ans,x);*/return ans;
}
int main(){
freopen("1.in","r",stdin);
re int i,j,h;scanf("%lld%d",&n,&k);G[0]=0;for(i=1;i<=k;i=j+1)j=k/(k/i),!G[k/i]&&(G[k/i]=++cnt,A[cnt]=k/i);A[cnt+1]=1e9;
now=n;while(now) m++,now/=10;for(i=1;i<=9;i++) F[1][i][G[k/i]]++;F[1][0][cnt+1]=1;
for(i=1;i<m;i++){
for(h=0;h<=cnt+1;h++){
for(j=0;j<=9;j++) H[i][h]+=F[i][j][h];
}
for(j=0;j<=cnt+1;j++)F[i+1][0][cnt+1]+=H[i][j];
for(j=1;j<=9;j++){
for(h=0;h<=cnt;h++)F[i+1][j][G[A[h]/j]]+=H[i][h]/*,printf("%d %d %d %d\n",i,j,h,G[A[h]/j])*/;
F[i+1][j][cnt+1]=H[i][cnt+1];
}
}
printf("%lld\n",find(m,G[k],1,pow(10,m-1)));
}
F
考试的时候没看这道题血亏。
仔细看题就可以知道大概要求\(\sum\limits_{i=1}^{n}{i^kC_{i+m}^{m}}\)
然后我们知道自然数幂和是\(k+1\)次,然后那个组合数是\(m\)次,所以是\(k+m+1\)次的一个多项式。
你先\(O(km)\)暴力递推然后拉格朗日插值即可。时间复杂度\(O(km+klogk)\)
code:
#include<bits/stdc++.h>
#define I inline
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define abs(x) ((x)>0?(x):-(x))
#define re register
#define ll long long
#define db double
#define N 3000000
#define M 30
#define mod 1000000007
#define eps (1e-7)
#define U unsigned int
#define IT set<ques>::iterator
#define Gc() getchar()
#define Me(x,y) memset(x,y,sizeof(x))
using namespace std;
int m,k,p;ll n,ToT,tmp=1,Ans[N+5],frc[N+5],inv[N+5],F[M+5][N+5],Q1[N+5],Q2[N+5];
I ll mpow(ll x,int y=mod-2){ll ans=1;while(y) (y&1)&&(ans=ans*x%mod),x=x*x%mod,y>>=1;return ans;}
I ll calc(ll k){
re int i;for(i=0;i<=p;i++) tmp=tmp*(k-i)%mod;for(Q1[0]=k,i=1;i<=p;i++) Q1[i]=Q1[i-1]*(k-i)%mod;for(Q2[p]=k-p,i=p-1;~i;i--) Q2[i]=Q2[i+1]*(k-i)%mod;
for(i=0;i<=p;i++)ToT+=inv[i]*((p-i)&1?mod-inv[p-i]:inv[p-i])%mod*Ans[i]%mod*(i?Q1[i-1]:1)%mod*(i==p?1:Q2[i+1])%mod;return (ToT%mod+mod)%mod;
}
int main(){
freopen("1.in","r",stdin);
re int i,j;scanf("%lld%d%d",&n,&m,&k);p=m+k;for(frc[0]=1,i=1;i<=p;i++) frc[i]=frc[i-1]*i%mod;inv[p]=mpow(frc[p]);for(i=p-1;~i;i--) inv[i]=inv[i+1]*(i+1)%mod;
for(i=0;i<=p;i++) F[0][i]=mpow(i,k);for(i=1;i<=m;i++) for(j=1;j<=p;j++) F[i][j]=(F[i][j-1]+F[i-1][j])%mod;
for(i=0;i<=p;i++)Ans[i]=F[m][i];printf("%lld\n",n<=p?Ans[n]:calc(n%mod));
}