【2016 泉市教科】幸运数

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

幸运数

题目描述

  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.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值