称一对字符串(A,B)是相似的,当且仅当满足以下条件:
(1)字符串A和B都恰好包含N个字符;
(2)A和B串中的每个字符都是小写字母的前k个字符,即A、B中只可能出现'a','b','c',...,('a'+k-1)这k个字符;
(3)存在一个字符串C,满足:A+C=C+B。这里的“+”号表示字符串间的链接,即str1+str2 = str1str2,如:“aaa”+“csd”=“aaacsd”。
例如,N=3,k=4那么("aad","daa")就是相似字符串对。
因为C="aa"时,有"aad"+"aa"="aadaa"="aa"+"daa".
现在给出N与k,问有多少种不同的相似字符串对,输出这个结果 mod 1,000,000,007的值。
说明:两个字符串对(A,B)与(C,D)是不同的,只要 A!=C 或 B!= D。
例如:N=2,k=2,一共有6种不同的相似字符串对,它们是: ("aa", "aa"), ("ab", "ab"),
("ab", "ba"), ("ba", "ab"), ("ba", "ba"), ("bb", "bb").
Input
一行2个整数N,k,其中1<=N<=1,000,000,000,1<=k<=26
Output
一个整数,即不同相似字符串对的数量 mod 1,000,000,007后的结果。
Input示例
2 2
Output示例
6
求满足条件的字符串的数量
思路:
找得到字符串C的条件是什么?怎么去计数?怎么防止重复计算?
在写一些小字符串手算方案数之后,发现其实问的就是:
长度为n的字符串,一共有k^n个,
对每个字符串拿一个后缀放到前面组成新串,再和原串组成的pair的个数
比如一个串xy可以组成(xy,xy),(xy,yx)
不考虑重复的话,答案就是k^n * n(空串也算一个后缀)
考虑重复后发现,
对于一个串str,可以写成循环的模式(s)k,表示由k个s连接可以形成str,并且使得
k最大,也就是|s|最小,那str可以组成的pair有|s|个,对答案贡献|s|
并且每一个str都可以写成循环的模式,因为str = (str)1
令f(i)表示|s|为i的字符串的方案数
则ans = ∑i|nf(i) * i
令g(i)表示|s|为i的约数的字符串的方案数
则:
g(i) = ki = ∑d|if(d)
反演以下就得到f的公式了,代入ans这个式子,再推一推,得到:
ans = ∑k|n k * Ak ∑j|n/k mu(j) * j
这里的A是输入的数据"k"
对于后面的求和,只需要考虑mu(j)不为0的情况,
一个固定的n/k,可以根号求素因子,再dfs枚举每个素因子要不要,求和
复杂度小于O(sqrt(n/k) + 2^10)
然后n最多大约有800个因子k
所以这里直接枚举k,对于每一个k"一次根号+一次dfs"求后面的求和式子是没问题的