zoukankan      html  css  js  c++  java
  • P5362 [SDOI2019]连续子序列 思维题

    题意:

    戳这里

    分析:

    不会分析 , 直接找规律:

    肉眼分析可以发现, (T.M) 序列的生成方式有两种:

    1. 取反然后复制一遍 (0110 o 01101001)
    2. ( iny color{white}{ ext{不}})容易发现 (0110 o 0(1)1(0)1(0)0(1))

    但是第一个性质不方便用,因为 (|S|+k) 不一定是 (2) 的整数次幂,所以我们考虑第二种方法

    我们发现在后面添加的 (k) 的布尔序列也会是 (01) ,(10) 交替的,所以一定不会存在连续的三个以上的相同字符,所以我们可以反向推导,由第二个性质可以知道 (0 o 01) (1 o 10) 所以我们每一次可以将 (S) 长度减半 (k) 也减半,这样递归 (log k) 层就能得到 (k<=2) 的情况,然后我们手动判掉 (n,k<=3) 的情况,顺便对 (S,k) 哈希一下之后记忆化

    具体来说就是,每次分两种情况讨论,一种是第一位空出来与前面的拼成一个 (0),第二种就是从第一位开始两个一组

    代码:

    #include<bits/stdc++.h>
    #define pii pair<int,int>
    #define mk(x,y) make_pair(x,y)
    #define lc rt<<1
    #define rc rt<<1|1
    #define pb push_back
    #define fir first
    #define sec second
    #define psl pair<string,long long>
    
    using namespace std;
    
    namespace zzc
    {
        typedef long long ll;
        const ll mod = 1e9+9;
        map<psl,ll> f;
        
        long long solve(string s,long long k)
        {
           if(f[mk(s,k)]) return f[mk(s,k)];
           long long n=s.size(),res=0;
           if(n==1&&k<=2) return k+1;
           if(n==2&&k==0) return 1;
           if(n==2&&k==1) return (s[0]==s[1])?1:2;
           if(n==3&&k==0) return (s[0]!=s[1]||s[1]!=s[2]);
           bool flag=true;
           string nxt;
           for(int i=0;i<n;i+=2)
           {
               if(i==n-1||s[i]!=s[i+1]) nxt+=s[i];
               else {flag=false;break;}
           }
           if(flag) res+=solve(nxt,(n&1)?(k>>1):((k+1)>>1))%mod;
           nxt=((s[0]-'0')^1)+'0';
           flag=true;
           for(int i=1;i<n;i+=2)
           {
               if(i==n-1||s[i]!=s[i+1]) nxt+=s[i];
               else {flag=false;break;}
           }
           if(flag) res+=solve(nxt,(n&1)?((k+1)>>1):(k>>1))%mod;
           return f[mk(s,k)]=res%mod;
        }
    
    	void work()
    	{
            ios::sync_with_stdio(false);
            string s;
            ll k,t;
            cin>>t;
            while(t--)
            {
                cin>>s>>k;
                cout<<solve(s,k)%mod<<'
    ';
            }
    	
    	}
    
    }
    
    int main()
    {
    	zzc::work();
    	return 0;
    }
    
    
  • 相关阅读:
    Android数字选择器-NumberPicker
    Eclipse上传代码到GitHub
    TortoiseGit上传代码到GitHub
    Git的简单介绍
    Android中的树状(tree)列表
    Android数据适配-ExpandableListView
    Android动画-补间(Tween)动画
    Android动画-帧动画
    Android中样式及主题
    Android消息通知-Notification
  • 原文地址:https://www.cnblogs.com/youth518/p/14255369.html
Copyright © 2011-2022 走看看