C.
发现枚举到1e5即可覆盖所有情况。
#include <bits/stdc++.h>
using namespace std;
int n,k,x;
bool vis[10];
int main(){
scanf("%d%d",&n,&k);
for (register int i=1; i<=k; ++i)
{
scanf("%d",&x);
vis[x]=true;
}
for (register int i=n; i<=99999; ++i)
{
bool jay=true;
int x=i;
while (x)
{
if (vis[x%10]) {jay=false; break;}
x/=10;
}
if (jay)
{
printf("%d\n",i);
break;
}
}
return 0;
}
D.
从(x,y)走到(xx,yy)的方案数为C(xx-x,xx-x+yy-y)。
枚举中间点,将整个图分两部分走完。
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N=2e5+5,MOD=1e9+7;
int n,m,A,B,ans;
int bin[N],inv[N];
inline int pow(int a,int n)
{
int res=1;
while (n)
{
if (n&1ll) res=res*a%MOD;
a=a*a%MOD;
n>>=1ll;
}
return res;
}
inline int C(int a,int b)
{
return bin[a]*inv[a-b]%MOD*inv[b]%MOD;
}
inline int solve(int sx,int sy,int tx,int ty)
{
return C(tx-sx+ty-sy,tx-sx);
}
signed main(){
bin[0]=inv[0]=1;
for (register int i=1; i<=2e5; ++i) bin[i]=bin[i-1]*i%MOD;
for (register int i=1; i<=2e5; ++i) inv[i]=pow(bin[i],MOD-2ll);
scanf("%lld%lld%lld%lld",&n,&m,&A,&B);
for (register int i=1; i<=n-A; ++i) ans=(ans+solve(1,1,i,B)*solve(i,B+1,n,m)%MOD)%MOD;
printf("%lld\n",ans);
return 0;
}
E.
考虑反着做,就不用去重了。
dp[i][p]:前i为填完了,填的数列能构成的数的集合为p。(p中第i位为1,表示数列能构成的数中有i)。
定义sum为符合条件的数列集合。
答案就是10^n减去所有p!=sum的情况。
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int MOD=1e9+7;
int n,x,y,z,sum,max_statue,ans;
int dp[41][1<<18];
signed main(){
scanf("%lld%lld%lld%lld",&n,&x,&y,&z);
sum=1<<(x+y+z-1);
sum|=1<<(y+z-1);
sum|=1<<(z-1);
max_statue=(1<<(x+y+z))-1;
dp[0][0]=1;
ans=1;
for (register int i=1; i<=n; ++i)
{
ans=ans*10%MOD;
for (register int p=0; p<=max_statue; ++p)
if (dp[i-1][p])
{
for (register int j=1; j<=10; ++j)
{
int now=(p<<j)|(1<<(j-1));
now&=max_statue;
if ((now&sum)!=sum) dp[i][now]=(dp[i][now]+dp[i-1][p])%MOD;
}
}
}
for (register int p=0; p<=max_statue; ++p) ans=(ans-dp[n][p]+MOD)%MOD;
printf("%lld\n",ans);
return 0;
}
F.
字符串比较大小无后效性,所以满足当前最优即可。
我们考虑构造k次答案,使得每一次的答案均为当前最优。
#include <bits/stdc++.h>
using namespace std;
const int N=2e3+5,M=1e4+5;
int n,k,cnt,ncnt;
int len[N];
char str[N][M],ans[M];
bitset<M>ok[N];
pair<int,int>p[2][N];
int main(){
scanf("%d%d",&n,&k);
for (register int i=1; i<=n; ++i) scanf("%s",str[i]+1),len[i]=strlen(str[i]+1);
ok[n+1][0]=1;
for (register int i=n; i>=1; --i) ok[i]=ok[i+1]|(ok[i+1]<<len[i]);
for (register int i=1; i<=n; ++i)
if (ok[i+1][k-len[i]]) p[0][++cnt]=make_pair(i,1);
int now=0;
for (register int i=1; i<=k; ++i)
{
char minn='z';
for (register int j=1; j<=cnt; ++j) minn=min(minn,str[p[now][j].first][p[now][j].second]);
ans[i]=minn;
int head=n+1;
ncnt=0;
for (register int j=1; j<=cnt; ++j)
{
int id=p[now][j].first,pos=p[now][j].second;
if (str[id][pos]!=minn) continue;
if (pos==len[id]) head=min(head,id+1);
else p[now^1][++ncnt]=make_pair(id,pos+1);
}
for (register int j=head; j<=n; ++j)
if (k-i-len[j]>=0 && ok[j+1][k-i-len[j]]) p[now^1][++ncnt]=make_pair(j,1);
cnt=ncnt;
now^=1;
}
puts(ans+1);
return 0;
}