kZjPBD.jpg

[20jint nhhhhfdgdfI. Skr

I. Skr

A number is skr, if and only if it's unchanged after being reversed. For example, "12321", "11" and "1" are skr numbers, but "123", "221" are not. FYW has a string of numbers, each substring can present a number, he wants to know the sum of distinct skr number in the string. FYW are not good at math, so he asks you for help.

Input

The only line contains the string of numbers SSS.

It is guaranteed that 1≤S[i]≤91 \le S[i] \le 91S[i]9, the length of SSS is less than 200000020000002000000.

Output

Print the answer modulo 100000000710000000071000000007.


样例输入1


111111

样例输出1


123456

样例输入2


1121

样例输出2


135


Solution

状压水题
差不多是个回文树的板子吧
建完树之后从0和1节点向下dfs就行了
dfs的时候算一下当前节点的值

CODE:


  1 #include <queue>
  2 #include <cstdio>
  3 #include <set>
  4 #include <string>
  5 #include <stack>
  6 #include <cmath>
  7 #include <climits>
  8 #include <map>
  9 #include <cstdlib>
 10 #include <iostream>
 11 #include <vector>
 12 #include <algorithm>
 13 #include <cstring>
 14 #define  ULL unsigned long long
 15 typedef long long ll;
 16 using namespace std;
 17 const int MAXN = 2e6+10 ;
 18 const ll MOD =1e9+7;
 19 const int N = 11 ;
 20 char s[MAXN];
 21 int hund[MAXN];
 22 struct Palindromic_Tree
 23 {
 24     int next[MAXN][N] ;//next指针,next指针和字典树类似,指向的串为当前串两端加上同一个字符构成
 25     int fail[MAXN] ;//fail指针,失配后跳转到fail指针指向的节点
 26     int cnt[MAXN] ;
 27     //int num[MAXN] ; // 当前节点通过fail指针到达0节点或1节点的步数(fail指针的深度)
 28     int len[MAXN] ;//len[i]表示节点i表示的回文串的长度
 29     int S[MAXN] ;//存放添加的字符
 30     int last ;//指向上一个字符所在的节点,方便下一次add
 31     int n ;//字符数组指针
 32     int p ;//节点指针
 33     int newnode(int l)     //新建节点
 34     {
 35         for(int i = 0 ; i < N ; ++ i) next[p][i] = 0 ;
 36         //cnt[p] = 0 ;
 37         //num[p] = 0 ;
 38         len[p] = l ;
 39         return p ++ ;
 40     }
 41     void init()   //初始化
 42     {
 43         p = 0 ;
 44         newnode(0) ;
 45         newnode(-1) ;
 46         last = 0 ;
 47         n = 0 ;
 48         S[n] = -1 ;//开头放一个字符集中没有的字符,减少特判
 49         fail[0] = 1 ;
 50     }
 51     int get_fail(int x)     //失配后,在回文串x中的所有后缀里找到一个串右端+s[n]依然构成回文串
 52     {
 53         //这里因为一定是从长的找到最短的,所以找到的一定是最长的
 54         while(S[n - len[x] - 1] != S[n]) x = fail[x] ;//判断此时S[n-len[last]-1]是否等于S[n]
 55         //即上一个串-1的位置和新添加的位置是否相同,相同则说明构成回文,否则,last=fail[last]。
 56         return x ;
 57     }
 58     void add(int c)   //cur,last,now都代表一个字符串,而不是一个下标/字符
 59     {
 60         c -= '0';
 61         S[++ n] = c ;   //n代表字符下标
 62         int cur = get_fail(last) ;   //通过上一个回文串找这个回文串的匹配位置
 63         //printf("%d ",cur);     //c+cur+c代表以c结尾的最长的回文串,cur对应原串中的位置就是以c前一个字符结尾的子串的位置
 64         if(!next[cur][c])     //如果这个回文串没有出现过,说明出现了一个新的本质不同的回文串
 65         {
 66             int now = newnode(len[cur] + 2) ;   //新建节点
 67             fail[now] = next[get_fail(fail[cur])][c] ;   //和AC自动机一样建立fail指针,以便失配后跳转
 68             next[cur][c] = now ;
 69             //num[now] = num[fail[now]] + 1 ;
 70         }
 71         last = next[cur][c] ;
 72         //cnt[last] ++ ;
 73     }
 74     void count()
 75     {
 76         for(int i = p - 1 ; i >= 0 ; -- i) cnt[fail[i]] += cnt[i] ;
 77         //父亲累加儿子的cnt,因为如果fail[v]=u,则u一定是v的子回文串!
 78     }
 79 } run;
 80 
 81 int ans;
 82 void dfs(int u,int val)
 83 {
 84     int v,inc;
 85     int tmp;
 86     for(int i=0; i<10; i++)
 87     {
 88         if(run.next[u][i])
 89         {
 90             v=run.next[u][i];
 91             tmp=run.len[v]-1?hund[run.len[v]-1]:0;
 92             inc=(val+i+1ll*i*tmp%MOD)%MOD;
 93             ans=(ans+inc)%MOD;
 94             dfs(v,1ll*inc*10%MOD);
 95         }
 96     }
 97 }
 98 
 99 
100 
101 int main()
102 {
103     scanf("%s",&s);
104     int n=strlen(s);
105     run.init();
106     for(int i=0; i<n; i++) run.add(s[i]);
107     hund[0]=1;
108     for(int i=1; i<=n; i++) hund[i]=1ll*hund[i-1]*10%MOD;
109     dfs(0,0);
110     dfs(1,0);
111     printf("%d\n",ans);
112     return 0;
113 
114 }

 

 
posted @ 2019-06-29 09:30  Through_The_Night  阅读(99)  评论(0)    收藏  举报