幸运数
题目描述
A君喜欢收集特殊的字符串,特別是那些能给他带来幸运的串。
A君认为一个串是幸运串当且仅当这个串包含长度大于1的回文子串。
A君想知道对于长度恰好为n且字符集大小为m的所有字符串中(字符集中字符不一定都要用 上),有多少个不同的幸运串呢?
最后的结果可能很大,A君只想知道答案对10^9 + 7取模后的值,请你帮助他。
输入
仅一行两个整数n,m,表示字符串长度5字符集大小。
输出
仅一行一个整数表示答案。
Sample input 1
3 3
Sample output 1
21
Sample input 2
44
Sample output 2
208
数据范围
30%的数据:n,m ≤7
60%的数据:n,m ≤10^7
100%的数据:1≤n,m≤10^18
题解
对于30%的数据,采用暴力模拟就好了
program lucky;
type st=array[0..3000] of longint;
const mo=1000000009;
var a,b:st;
i,j,m,n,ans,g:longint;
function check(c:st;k:longint):boolean;
var i,j,g:longint;flag:boolean;
begin
flag:=true;
for i:=1 to k-1 do
for j:=i+1 to k do
begin
flag:=true;
for g:=0 to (j-i) div 2 +1 do
if c[i+g] <> c[j-g] then
begin
flag:=false;
break;
end;
if flag then exit(true);
end;
exit(false);
end;
procedure dfs(k:longint);
var i,j,tmp:longint;
begin
tmp:=1;
for i:=1 to m do
begin
b[k]:=i;
if k>n then exit;
if k=n then
if check(b,n) then inc(ans);
if k<n then
dfs(k+1);
end;
end;
procedure putin;
begin
assign(input,'lucky.in');reset(input);
assign(output,'lucky.out');rewrite(output);
end;
procedure outit;
begin
close(input);close(output);
end;
begin
putin;
read(n,m);
dfs(1);
writeln(ans) ;
outit;
end.
100%的解法
对于这串幸运数,我们可以去寻找不是幸运数的个数,再把所有等可能性减去该个数,即可得到最终答案。对于该题,我们可以分析得出,第一位有m种选择方案数,而若不包含回文串,则第二位不能与第一位相同(如aa),第三位也不能与第一位相同,如(aba),因而方案数可以得出以下公式:
(m^n)-(m)×(m-1)×(m-2)^(n-2)
而该题数据点较大,因此读入时就要进行取模,然后,一边做一边膜一膜
program lucky;
const mo=1000000007;
var n,m,ans:int64;
i,j,k:longint;
function fpm(a,b:int64):int64; //快速幂
var t,y:int64;
begin
t:=1;y:=a;
while b<>0 do
begin
if (b and 1)=1 then t:=t*y mod mo;
y:=y*y mod mo;
b:=b shr 1;
end;
exit(t);
end;
begin
read(n,m);
m:=m mod mo;
if n=1 then ans:=0
else
ans:=(fpm(m,n) -m*(m-1) mod mo * fpm((m-2 + mo) mod mo,n-2)mod mo +mo) mod mo;
writeln(ans);
end.

本文介绍了一个算法问题,即计算长度为n且字符集大小为m的所有字符串中,包含长度大于1的回文子串的数量。提供了针对不同规模数据的解决方案,并通过取模操作确保结果在限定范围内。
905

被折叠的 条评论
为什么被折叠?



