传送门
MUV LUV EXTRA
Time Limit: 2000/1500 MS (Java/Others) Memory Limit: 262144/262144 K (Java/Others)Total Submission(s): 1586 Accepted Submission(s): 484
Sumika guesses that the answer is a rational number, which means that there exists two integers p, q that the answer equals qp) in decimal form, denoting the first some digits of the accurate result.
It is guaranteed that there is exactly one decimal point in s and s is a legal non-negative decimal without leading "-"(the minus sign).
5 3 1.1020 2 1 12.1212
9 6
题意:
纯夏希望从这个无限小数的前n位猜出原本的数字。纯夏意识到,猜测的循环节太长或循环节已经开始出现的部分长度太短是不可信的。举个例子,若她量出的小数为1.0285714285714,显然假设循环节为0285714285714(长度为13)或假设循环节为428571(已经开始出现的部分长度为7)都不如假设循环节为285714(长度为6,已经开始出现的部分长度为12)可靠。因此她定义一个循环节的可靠程度为a×循环节已经开始出现的部分长度−b×循环节长度。请你帮她求出最可靠的循环节的可靠程度为多少。
样例解释
对于第1组样例:
若猜测循环节为0,则可靠度=5×1−3×1=2;
其中,我们把以 0 为循环节的小数也看作无限循环小数。
若猜测循环节为20,则可靠度=5×2−3×2=4;
若猜测循环节为02,则可靠度=5×3−3×2=9;
若猜测循环节为020,则可靠度=5×3−3×3=6;
若猜测循环节为1020,则可靠度=5×4−3×4=8。
对于第2组样例:
若猜测循环节为2,则可靠度=2×1−1×1=1;
若猜测循环节为12,则可靠度=2×4−1×2=6;
若猜测循环节为21,则可靠度=2×3−1×2=4;
若猜测循环节为212,则可靠度=2×3−1×3=3;
若猜测循环节为1212,则可靠度=2×4−1×4=4。
注意,计算循环节可靠度的时候不考虑整数部分。输入中给出的整数部分只是为了还原纯夏见到的数字。
就是按照他的定义和计算方法找一下最大值
思路:
首先循环节长度,学过KMP就知道,一段字符(长度为i)的循环节长度等于i-next[i]
因为循环节在后面,所以把小数点后面的字符倒置,求一下next,然后求最大值即可
a*循环节已经开始出现的部分长度,就是当前字符串的长度
字符串从0开始的,写出i+1即可
代码:
int nex[MAXN];
char p[MAXN];
char s[MAXN];
void getnext(int nex[],char p[])
{
int len=strlen(p);
nex[0]=-1;
int j=-1;
int i=0;
while(i<len)//原来这里是len-1,没有算到最后一个的nex,因为用的i+1,要多算一位
{
if(j==-1||p[i]==p[j]){
i++,j++;
nex[i]=j;
}
else
j=nex[j];
}
}
int main()
{
std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
ll ans=-1e18;
ll a,b;
while(cin>>a>>b){
ans=-1e18;
cin>>s;
int n=strlen(s);
int f=0;
int cnt=0;
for(int i=0;i<n;i++){
if(f==1){
p[cnt++]=s[i];
}
if(s[i]=='.')f=1;
}
reverse(p,p+cnt);
for(int i=0;i<=cnt;i++)nex[i]=0;
getnext(nex,p);
for(int i=0;i<cnt;i++){
//cout<<nex[i+1]<<" ";
ans=max(ans,1ll*a*(i+1)-1ll*b*(i+1-nex[i+1]));
}
//cout<<endl;
cout<<ans<<endl;
}
return 0;
}