hdu4632

/*
分析:
    (找规律+递推) && (线段树 || 树状数组),非区间dp方法。
    以后都不准备再贴水题了,不过这题我比赛时想到的方法和解题报告的方法不一样,所
以贴下。。

    1. 经过观察,发现性质:对于str[i]==str[j]  && i (i 文序列,并且这个回文序列的首元素为str[i]、尾元素为str[j];
    2. 维护两个数组,ans[N]和cnt[N],ans[i]表示以元素i为首位的回文序列的数量、cnt[i]表
示以元素i结尾的回文序列的数量;
    3. 逆向遍历str(正向也行),初始化ans[i]=1,cnt[i]=1,代表自己单独为一个序列;同
时用指针j,从str尾向前遍历while(i         (1)ans[i]++,cnt[j]++,(代表i和j单独构成一个序列);
        (2)统计sum=所有cnt[k]的和,k满足(i         
    最后统计所有的ans的SUM,既为所求。
    对于3.(2),需要用树状数组或者线段树快速求和。
    
源自------------------------------------- Ice_Crazy

                                                                    2013-08-02
*/







#include"iostream"
#include"cstdio"
#include"cstring"
using namespace std;
const int N=1006;
const int mod=10007;


int n,lowbit[N];
__int64 C[N],ans[N];
char str[N];

void update(int k,int dir)
{
    while(0>T;
    for(Case=1;Case<=T;Case++)
    {
        hehe=0;
        scanf("%s",str+1);

        memset(C,0,sizeof(C));
        memset(ans,0,sizeof(ans));
        for(n=1;str[n];n++);
        n--;

        for(i=n;i>=1;i--)
        {
            ans[i]=1;
            update(i,1);
            for(l=n;l>i;l--)
            {
                if(str[l]==str[i])
                {
                    a=sum(i);
                    b=sum(l-1);
                    t=(b-a)%mod;
                    while(t<0)    t+=mod;
                    ans[i]=(ans[i]+1+t)%mod;
                    update(l,1+t);
                }
            }
        }

        hehe=0;
        for(i=1;i<=n;i++)    hehe=(hehe+ans[i])%mod;
        printf("Case %d: %I64d\n",Case,hehe);
    }
    return 0;
}


你可能感兴趣的:(数据结构,regional&&multi)