1209邮寄
省流
A
人均过$A$,不讲了找规律
预计得分:100
实际得分:100
B
暴搜
没打,输出了一个NO
预计得分:0
实际得分:0
C
暴搜
输出-1,10分
D
没看题
主观感受
挂了$100$分无语....
A
可以打表找规律,并发现对于 $n > 17$ 的构成方案必定是在 $n - 7$后加一个 $8$,但是我用的贪心,虽然一定程度上避免了一些坑,但是耗费了较长时间
在考场写的屎山代码:
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e5+50;
const int mod=998244853;
int T,n,ans[N],limit,res;
char s[N];
int qpow(int a,int b){
int res=1;
while(b){
if(b&1)res=res*a%mod;
a=a*a%mod;
b>>=1;
}
return res;
}
signed main(){
// freopen("stick.in","r",stdin);
// freopen("stick.out","w",stdout);
scanf("%d",&T);
ans[2]=1;
ans[3]=7;
ans[4]=4;
ans[5]=2;
ans[6]=0;
ans[7]=8;
ans[8]=10;
ans[9]=18;
ans[10]=22;
ans[11]=20;
s[0]='0',s[1]='2';limit=2;
int last8=0;
for(int i=12;i<=100000;i++){
int cnt=1;bool flag=true;
for(int j=last8;j<limit;j++){
if(s[j]!='8')flag=false;
if(s[j]=='0'){
last8=j;
s[j]='8';
ans[i]=(ans[i-1]+qpow(10,j)*8%mod)%mod;
break;
}else if(s[j]=='6'){
last8=j;
s[j]='8';
ans[i]=(ans[i-1]+qpow(10,j)*2%mod)%mod;
break;
}else if(s[j]=='1'){
s[j]='2';
s[j-1]='0';
s[j-2]='0';
ans[i]=(ans[i-1]+qpow(10,j)*1%mod-8*qpow(10,j-1)-8*qpow(10,j-2))%mod;
last8=j-3;
break;
}else if(s[j]=='2'){
if(j+1<limit)s[j]='0',ans[i]=(ans[i-1]-qpow(10,j)*2%mod)%mod;
else s[j]='6',ans[i]=(ans[i-1]+qpow(10,j)*4%mod)%mod;
break;
}
}
if(flag){
ans[i]=(ans[i-1]-8*qpow(10,limit-1)%mod+1*qpow(10,limit)%mod+mod)%mod;
s[limit-1]='0';
last8=limit-2;
s[limit]='1';
limit++;
}
ans[i]=(ans[i]+mod)%mod;
}
while(T--){
scanf("%d",&n);
printf("%d\n",ans[n]);
}
return 0;
}
B
复杂度玄学,暴力可过。
补题代码:
#include<bits/stdc++.h>
using namespace std;
string s[35];
char b[100005];
int n,m,T,cnt,sx,sy,tx,ty,xx,yy;
bool fl;
bool flyto(int x,int y,int k)
{
if(k==1)
{
for(;x>=1;x--)
{
if(s[x][y]=='.')
{
xx=x,yy=y;
return true;
}
}
}
if(k==2)
{
for(;x<=n;x++)
{
if(s[x][y]=='.')
{
xx=x;yy=y;
return true;
}
}
}
if(k==3)
{
for(;y>=1;y--)
{
if(s[x][y]=='.')
{
xx=x;yy=y;
return true;
}
}
}
if(k==4)
{
for(;y<=m;y++)
{
if(s[x][y]=='.')
{
xx=x;yy=y;
return true;
}
}
}
return false;
}
void dfs(int x,int y,int di,int sep)
{
if(fl)return;
if(x==tx&&y==ty)
{
if(sep==cnt)
{
fl=true;
cout<<"YES\n";
for(int i=0;i<sep;i++)cout<<b[i];
}
return;
}
if(di!=2)
{
if(flyto(x,y,1))
{
int xxx=xx,yyy=yy;
s[xx][yy]='#';
b[sep]='U';
dfs(xx,yy,1,sep+1);
s[xxx][yyy]='.';
}
}
if(di!=1)
{
if(flyto(x,y,2)){
int xxx=xx,yyy=yy;
s[xx][yy]='#';
b[sep]='D';
dfs(xx,yy,2,sep+1);
s[xxx][yyy]='.';
}
}
if(di!=3)
{
if(flyto(x,y,4))
{
int xxx=xx,yyy=yy;
s[xx][yy]='#';
b[sep]='R';
dfs(xx,yy,4,sep+1);
s[xxx][yyy]='.';
}
}
if(di!=4)
{
if(flyto(x,y,3))
{
int xxx=xx,yyy=yy;
s[xx][yy]='#';
b[sep]='L';
dfs(xx,yy,3,sep+1);
s[xxx][yyy]='.';
}
}
return;
}
int main(){
// ios::sync_with_stdio(false);
// cin.tie(0);cout.tie(0);
cin>>T;
while(T--){
cnt=0;fl=false;
cin>>n>>m;
for(int i=1;i<=n;i++)
{
cin>>s[i];
s[i]=" "+s[i];
for(int j=1;j<=m;j++)
{
if(s[i][j]=='.')cnt++;
if(s[i][j]=='S')sx=i,sy=j,s[i][j]='#';
if(s[i][j]=='T')tx=i,ty=j,s[i][j]='.',cnt++;
}
}
dfs(sx,sy,0,0);
if(!fl)cout<<"NO";
cout<<'\n';
}
return 0;
}
C
由于题目要求第 $k$ 大字典序且 $k \le 1000$,可以考虑用爆搜搜出前 $k$ 个解
同时,为了保证所得到的解的权值都大于 $x$,需要先倒序 $dp$ 求最大值,如果可以就继续搜,不可以就剪枝。
D
区间$DP$白学了