真的是下定了巨大的決心來搞這一講,果不其然耗了一晚上
開車旅行(真的是noip的題嗎怎麼這麼恐怖)
首先,先用set把小a和小b從城市i出發,到達的下乙個城市預處理出來。
f[i][j][k]表示走了2^i天,j城市出發,k表示誰開車,到達那個城市。
轉移就是f[i][j][k]=f[i-1][f[i-1][j][k]][k] 相信很好理解
特別的i-1==0時,因為k是奇數,開車的人是變化的,所以f[i][j][k]=f[i-1][f[i-1][j][k]][k^1]
令da[i][j][k],db[i][j][k],分別表示小a和小b這個狀態下走的路程
對於詢問1,列舉所有的城市作為起點,然後基於二進位制劃分的思想,倒著for一步步在滿足走的總路程<=x0的情況下前進,這樣可以計算出小a走的路程和小b走的路程。找最大比值即可。
詢問二就直接詢問小a走的路程和小b走的路程了。同理可求。
#include#include開車旅行#include
#include
#include
#include
#include
using
namespace
std;
typedef
long
long
ll;int h[110000
];struct
snode
snode(
int id,int h)
friend
bool
operator
};set
s;set
::iterator it,lt,rt;
int g[110000
],i;
bool cmp(int g1,int g2)
int ago[110000],bgo[110000
];int f[22][110000][2]; ll da[22][110000][2],db[22][110000][2
];ll a,b;
void solve(int now,int
x0)}
intmain()
rt++;
if(rt!=s.end())
i=i;sort(g+1,g+m+1
,cmp);
if(m>1)ago[i]=g[2
];
if(m>0)bgo[i]=g[1
]; }
memset(f,
0,sizeof
(f));
for(int i=1;i<=n;i++)
for(int i=1;i<=20;i++)
for(int j=1;j<=n;j++)
for(int k=0;k<=1;k++)
}int x0,ans;ll ansa=1,ansb=0
; scanf("%d
",&x0);
for(int i=1;i<=n;i++)
printf(
"%d\n
",ans);
intq,x,y;
scanf("%d
",&q);
while(q--)
return0;
}
count the repetitions
f[j][i]表示從s1第i個字元開始,能夠表示出s2 2^j最少需要多少字元。
就有f[j][i]=f[j-1][i]+f[j-1][((i+f[j-1][i])-1)%s1len+1]
最後就列舉匹配的起始點,同樣在不超過s1len*n1的情況下用二進位制一步步跳,記錄當前起始點的最優解更新答案就好了。
#include#includecount the repetitions#include
#include
#include
#include
using
namespace
std;
typedef
long
long
ll;
char s1[110],s2[110
];ll f[
40][110
];int
main()
')break
; scanf(
"%d%s%d
",&n2,s1+1,&n1);
int s2len=strlen(s2+1),s1len=strlen(s1+1
);
bool bk=false
;
for(int i=1;i<=s1len;i++)
}p=p%s1len+1
; f[
0][i]+=cc+1
;
if(bk==true)break
; }
if(bk==true)break
; }
if(bk==true)continue
;
for(int j=1;j<=30;j++)
for(int i=1;i<=s1len;i++)
f[j][i]=f[j-1][i]+f[j-1][((i+f[j-1][i])-1)%s1len+1
];
ll m=0
;
for(int i=1;i<=s1len;i++)
printf(
"%lld\n
",m/n2);
}return0;
}
好像都是先預處理出下一步的狀態,然後二進位制劃分啊