ACM-ICPC 2018 焦作赛区网络预赛 H、L

https://nanti.jisuanke.com/t/31721

题意 n个位置 有几个限制相邻的三个怎么怎么样,直接从3开始 矩阵快速幂进行递推就可以了

  1 #include <bits/stdc++.h>
  2 using namespace std;
  3 typedef long long ll;
  4 const ll mod=1e9+7,maxn=9;
  5 struct Matrix
  6 {
  7     ll m[maxn][maxn];
  8     Matrix()
  9     {
 10         memset(m,0,sizeof(m));
 11     }
 12     void init()
 13     {
 14         for(int i=0; i<maxn; i++)
 15             for(int j=0; j<maxn; j++)
 16                 m[i][j]=(i==j);
 17     }
 18     Matrix  operator +(const Matrix &b)const
 19     {
 20         Matrix c;
 21         for(int i=0; i<maxn; i++)
 22         {
 23             for(int j=0; j<maxn; j++)
 24             {
 25                 c.m[i][j]=(m[i][j]+b.m[i][j])%mod;
 26             }
 27         }
 28         return c;
 29     }
 30     Matrix  operator *(const Matrix &b)const
 31     {
 32         Matrix c;
 33         for(int i=0; i<maxn; i++)
 34         {
 35             for(int j=0; j<maxn; j++)
 36             {
 37                 for(int k=0; k<maxn; k++)
 38                 {
 39                     c.m[i][j]=(c.m[i][j]+(m[i][k]*b.m[k][j])%mod)%mod;
 40                 }
 41             }
 42         }
 43         return c;
 44     }
 45     Matrix  operator^(const ll &t)const
 46     {
 47         Matrix ans,a=(*this);
 48         ans.init();
 49         ll n=t;
 50         while(n)
 51         {
 52             if(n&1) ans=ans*a;
 53             a=a*a;
 54             n>>=1;
 55         }
 56         return ans;
 57     }
 58 };
 59 int xishu[9][9]={
 60 0,0,0,1,0,0,1,0,0,
 61 1,0,0,1,0,0,1,0,0,
 62 1,0,0,1,0,0,0,0,0,
 63 0,1,0,0,1,0,0,1,0,
 64 0,1,0,0,0,0,0,1,0,
 65 0,1,0,0,1,0,0,0,0,
 66 0,0,1,0,0,0,0,0,1,
 67 0,0,0,0,0,1,0,0,1,
 68 0,0,1,0,0,1,0,0,0};
 69 int main()
 70 {
 71     int t;
 72     ll n,m,a,b;
 73     scanf("%d",&t);
 74     while(t--)
 75     {
 76         scanf("%lld",&n);
 77         if(n==1)
 78         {
 79             printf("3
");
 80             continue;
 81         }
 82         if(n==2)
 83         {
 84             printf("9
");
 85             continue;
 86         }
 87         Matrix temp,aa;
 88         for(int i=0;i<maxn;i++)
 89         {
 90             for(int j=0;j<maxn;j++)
 91             {
 92                 temp.m[i][j]=xishu[i][j];
 93             }
 94         }
 95         for(int i=0;i<maxn;i++)
 96             aa.m[i][0]=1;
 97         temp=temp^(n-2);
 98         aa=temp*aa;
 99         ll ans=0;
100         for(int i=0;i<maxn;i++)
101             ans=(ans+aa.m[i][0])%mod;
102         cout<<ans<<endl;
103     }
104     return 0;
105 }

https://nanti.jisuanke.com/t/31717

解析 傻逼题,数据范围应该是2e5,真是傻逼,被安排的明明白白。存个后缀自动机的板子。

#include<bits/stdc++.h>
using namespace std;
const int maxn = 2e5+5;
typedef long long ll;
char s[maxn];
int len,k,n,m;
char temp[5];
struct SAM{
    int last,cnt,nxt[maxn*2][26],fa[maxn*2],l[maxn*2],num[maxn*2];
    ll ans;
    void init(){
        last = cnt=1;
        memset(nxt[1],0,sizeof nxt[1]);
        fa[1]=l[1]=num[1]=0;
        ans=0;
    }
    int inline newnode(){
        cnt++;
        memset(nxt[cnt],0,sizeof nxt[cnt]);
        fa[cnt]=l[cnt]=num[cnt]=0;
        return cnt;
    }
    void add(int c){
        int p = last;
        int np = newnode();
        last = np;
        l[np] =l[p]+1;
        while (p&&!nxt[p][c]){
            nxt[p][c] = np;
            p = fa[p];
        }
        if (!p){
            fa[np] =1;
        }else{
            int q = nxt[p][c];
            if (l[q]==l[p]+1){
                fa[np] =q;
            }else{
                int nq = newnode();
                memcpy(nxt[nq],nxt[q],sizeof nxt[q]);
                fa[nq] =fa[q];
                num[nq] = num[q];
                l[nq] = l[p]+1;
                fa[np] =fa[q] =nq;
                while (nxt[p][c]==q){
                    nxt[p][c]=nq;
                    p = fa[p];
                }
            }
        }
        int temp = last;
        while (temp){
            if (num[temp]>=k){
                break;
            }
            num[temp]++;
            if (num[temp]==k){
                ans+=l[temp]-l[fa[temp]];
            }
            temp = fa[temp];
        }
    }
}sam;
int main(){
    while (scanf("%s",s)!=EOF){
        scanf("%d%d",&m,&k);k++;
        n=len = strlen(s);
        sam.init();
        for (int i=0;i<len;i++){
            sam.add(s[i]-'A');
        }
        ll ans1=sam.ans;
        k=m;
        sam.init();
        for (int i=0;i<len;i++){
            sam.add(s[i]-'A');
        }
        ll ans2=sam.ans;
        printf("%lld
",ans2-ans1);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/stranger-/p/9657101.html