XJOI NOIP501 / 511 22 ttt training school string

ttt school string

Subject to the effect

Grand Master ttt recent study of string, one day he saw the magic xtx A string left hand, right hand holding a B string, the length of the two strings are the same, and three character classes constituted by abc, Grand Master ttt spiritual power is C, to tell you now become a changed bb c and c, respectively, a varying value of spiritual power consumption needs (other conversion does not exist), ask your spiritual power within the range of up to ttt there are many different schemes can be converted from serial xtx left to right sequence xtx

Input formats:

The first two lines of the same two input length of the string, the first string represents a string of left-hand, right-hand second string represents a string, the string can not be changed right
third line of the input three integers representing the cost of transition cost_ab cost_bc cost_ca 
fourth row enter an integer value of spiritual power of ttt

Output formats:

A data output for each number represents the answer

Legitimate answer is ordered to 1e9 + 7 operand modulo sequence,

Sample input:

a
a
1 2 3
12

Sample output:

3

Sample explained:

The first scenario: you can not spend the price has reached the purpose of 
the second option: the cost of spending 6 from a -> b -> c -  > a
third option: The second program repeat

data range:

n is the length of the string

  • 30%, n <= 5, max(cost_ab, cost_bc, cost_ca) <= 5, C <= 20
  • 60%, n <= 5, max(cost_ab, cost_bc, cost_ca) <= 100, C <= 1000
  • 100%, n <= 11, max(cost_ab, cost_bc, cost_ca) <= 100, C <= 1000000000

time limit:

1000 ms

Space limitations:

32 MB

 

Fast Power matrix DP +

60 points:

Note $ dp [i] [j] [k] $ i is represented by the times after the magic string A and string B has the same $ i $ a, can be obtained by a change of the same with a $ a $ J

$ $ N-length string

It can be obtained by varying the two have a $ nij $

So once magic may have three options: to change the same, there is a change of change, change there are two changes

Transfer equation

$dp[i][j][k]=dp[i-1][j-1][k+1]*(k+1)+dp[i-1][j][k-1]*(n-j-k+1)+dp[i-1][j+1][k]*(j+1)$

So now feasible to consider whether these states

Processing a first minimum cost string A to string B is the number

Because after the same change, during the change operation requires 3

It can calculate the maximum number of operational steps $ step $

Then the answer is $ \ sum_ {i = 0} ^ {step} dp [i] [n] [0] $

#include <bits/stdc++.h>
#define mod 1000000007
#define ll long long
using namespace std;
ll ab,bc,ca,C,dp[1100][7][7];
ll t0,t1,n,step,cost,tot,ans;
string a,b;
int main()
{
    cin>>a>>b;
    scanf("%lld%lld%lld%lld",&ab,&bc,&ca,&C);
    tot=ab+bc+ca;
    for (ll i=0;i<(ll)a.size();i++)
    {
        if (a[i]==b[i])
          t0++;
        else
        {
            if (a[i]=='c' && b[i]=='a')
              t1++;
            if (a[i]=='b' && b[i]=='c')
              t1++;
            if (a[i]=='a' && b[i]=='b')
              t1++;
        }
    }
    for (ll i=0;i<(ll)a.size();i++)
    {
        if (a[i]==b[i])
          continue;
        if (a[i]=='a' && b[i]=='b')
          cost+=ab,step++;
        if (a[i]=='a' && b[i]=='c')
          cost+=ab+bc,step+=2;
        if (a[i]=='b' && b[i]=='c')
          cost+=bc,step++;
        if (a[i]=='b' && b[i]=='a')
          cost+=bc+ca,step+=2;
        if (a[i]=='c' && b[i]=='a')
          cost+=ca,step++;
        if (a[i]=='c' && b[i]=='b')
          cost+=ca+ab,step+=2;
    }
    if (cost>C)
    {
        printf("0\n");
        return 0;
    }
    step+=3*((C-cost)/tot);//计算最大步数
    dp[0][t0][t1]=1;//初始状态
    n=(ll)a.size();
    for (ll i=1;i<=step;i++)
    {
        for (ll j=0;j<=n;j++)
        {
            for (ll k=0;k<=n;k++)
            {
                if (j+k>n)
                  break;
                if (j>0 && k<n)
                  dp[i][j][k]=(dp[i][j][k]+dp[i-1][j-1][k+1]*(k+1)%mod)%mod;
                if (k>0)
                  dp[i][j][k]=(dp[i][j][k]+dp[i-1][j][k-1]*(n-j-k+1)%mod)%mod;
                if (j<n)
                  dp[i][j][k]=(dp[i][j][k]+dp[i-1][j+1][k]*(j+1)%mod)%mod;
            }
        }
    }
    for (ll i=0;i<=step;i++)
      ans=(ans+dp[i][n][0])%mod;//累加答案
    printf("%lld\n",ans);
}

100 points:

This shift can be found by matrix equation optimization

In the matrix as long as the recording layer prior to the value dp

And fill in the corresponding transition matrix $ tr $

However, because the answer is $ dp [i] [n] [0] $ prefix and, the need to handle each $ dp [i] [n] [0] $

The initial matrix is ​​denoted $ f $

Then the matrix need to be addressed to

$f+f*tr+f*tr^{2}+...+f*tr^{step}$

 

This is the summation of geometric matrix problem

Detailed

 

Transfer to

#include <bits/stdc++.h>
#define mod 1000000007
#define ll long long
using namespace std;
ll ab,bc,ca,C,id[15][15][15];
ll t0,t1,n,step,cost,tot,ans,cnt;
string a,b;
struct node
{
    ll n,num[300][300];
    void init()
    {
        for (ll i=1;i<=n;i++)
          num[i][i]=1;
    }
    void prepare()
    {
        for (ll i=1;i<=n;i++)
        {
            for (ll j=1;j<=n;j++)
              num[i][j]=0;
        }
    }
    void print()
    {
        for (ll i=1;i<=n;i++)
        {
            for (ll j=1;j<=n;j++)
              printf("%lld ",num[i][j]);
            printf("\n");
        }
    }
}tr,f;
node A;
node operator * (node a,node b)
{
    node c;
    c.n=a.n;
    c.prepare();
    for (ll i=1;i<=a.n;i++)
    {
        for (ll j=1;j<=a.n;j++)
        {
            for (ll k=1;k<=a.n;k++)
            {
                c.num[i][j]=(c.num[i][j]+a.num[i][k]*b.num[k][j])%mod;
            }
        }
    }
    return c;
}
node m_pow(node a,ll b)
{
    node c;
    c.n=a.n;
    c.prepare();
    c.init();
    while (b>0)
    {
        if (b&1)
          c=c*a;
        b>>=1;
        a=a*a;
    }
    return c;
}
int main()
{
    cin>>a>>b;
    scanf("%lld%lld%lld%lld",&ab,&bc,&ca,&C);
    tot=ab+bc+ca;
    for (ll i=0;i<(ll)a.size();i++)
    {
        if (a[i]==b[i])
          t0++;
        else
        {
            if (a[i]=='c' && b[i]=='a')
              t1++;
            if (a[i]=='b' && b[i]=='c')
              t1++;
            if (a[i]=='a' && b[i]=='b'++
              T1);
        }
    }
    for (ll i=0;i<(ll)a.size();i++)
    {
        if (a[i]==b[i])
          continue;
        if (a[i]=='a' && b[i]=='b')
          cost+=ab,step++;
        if (a[i]=='a' && b[i]=='c')
          cost+=ab+bc,step+=2;
        if (a[i]=='b' && b[i]=='c')
          cost+=bc,step++;
        if (a[i]=='b' && b[i]=='a')
          cost+=bc+ca,step+=2;
        if (a[i]=='c' && b[i]=='a')
          cost+=ca,step++;
        if (a[i]=='c' && b[i]=='b')
          cost+=ca+ab,step+=2;
    }
    if (cost>C)
    {
        printf("0\n");
        return 0;
    }
    n=(ll)a.size();
    step+=3*((C-cost)/tot);
    for (ll i=0;i<=n;i++)
    {
        for (ll j=0;j<=n;j++)
        {
            for (ll k=0;k<=n;k++)
            {
                if (i+j+k!=n)
                  continue; 
                CNT ++ ; 
                ID [I] [J] [K] = CNT;
                 IF (&& J == I == T0 T1) 
                  f.num [ . 1 ] [CNT] = . 1 ; // fill initial matrix 
            } 
        } 
    } 
    for (LL I = 0 ; I <= n-; I ++ ) // fill The DP transfer equation transfer matrix 
    { 
        for (LL J = 0 ; J <= n-; J ++ ) 
        { 
            for (LL K = 0 ; K < n-=; K ++ ) 
            { 
                IF ! (I + J + K = n-)
                   Continue;
                if (i>0 && j<n)
                  tr.num[id[i-1][j+1][k]][id[i][j][k]]=j+1;
                if (j>0 && k<n)
                  tr.num[id[i][j-1][k+1]][id[i][j][k]]=k+1;
                if (i<n && k>0)
                  tr.num[id[i+1][j][k-1]][id[i][j][k]]=i+1;
            }
        }
    }
    f.n=tr.n=cnt;
    A.n=cnt*2;//计算等比矩阵求和
    A.prepare();
    for (ll i=1;i<=tr.n;i++)
    {
        for (ll j=1;j<=tr.n;j++)
          A.num[i][j]=A.num[i][j+tr.n]=tr.num[i][j];
    }
    for (ll i=tr.n+1;i<=2*tr.n;i++)
    {
        for (ll j=tr.n+1;j<=2*tr.n;j++)
        {
            if (i==j)
              A.num[i][j]=1;
        }
    }
    A=m_pow(A,step);
    for (ll i=1;i<=tr.n;i++)
    {
        for (ll j=tr.n+1;j<=2*tr.n;j++)
          tr.num[i][j-tr.n]=A.num[i][j];
    }
    f=f*tr;
    if (t0==n && t1==0)
      f.num[1][id[n][0][0]]++;
    printf("%lld\n",f.num[1][id[n][0][0]]);
}

 

Guess you like

Origin www.cnblogs.com/huangchenyan/p/11482035.html