zoukankan      html  css  js  c++  java
  • CF1097H

    题意

    洛谷

    做法

    (f_{i,j})为第i轮得到的序列,假设j后的状态,状态维护序列的答案,(pre_i,suf_i)

    (suf_i):其长度为(i)的后缀是否能成为可行串长度为(i)的前缀
    (pre_i):其长度为(n-i)的前缀是否能成为可行串长度为(n-i)的后缀

    合并类似于线段树,然后(pre,suf)用bitset优化

    code

    这里copy来的

    #include<bits/stdc++.h>
    using namespace std;
    
    #define rep(i,l,r) for(register int i = l ; i <= r ; i++)
    #define repd(i,r,l) for(register int i = r ; i >= l ; i--)
    #define rvc(i,S) for(register int i = 0 ; i < (int)S.size() ; i++)
    #define rvcd(i,S) for(register int i = ((int)S.size()) - 1 ; i >= 0 ; i--)
    #define fore(i,x)for (register int i = head[x] ; i ; i = e[i].next)
    #define forup(i,l,r) for (register int i = l ; i <= r ; i += lowbit(i))
    #define fordown(i,id) for (register int i = id ; i ; i -= lowbit(i))
    #define pb push_back
    #define prev prev_
    #define stack stack_
    #define mp make_pair
    #define fi first
    #define se second
    #define lowbit(x) (x&(-x))
    
    typedef long long ll;
    typedef long double ld;
    typedef unsigned long long ull;
    typedef pair<int,int> pr;
    
    const ll inf = 2e18;
    const int N = 3e4 + 10;
    const int maxn = 2000020;
    const ll mod = 1e9 + 7;
    
    struct node{
    	ll num,len;
    	bitset <N> pre,suf;
    	node() { num = len = 0; pre.reset(),suf.reset(); }
    }f[70][62];
    int gen[120],n,m,d,B[N];
    ll l,r,pow_[70];
    int a[maxn];
    bitset <N> all;
    
    node merge(const node &a,const node &b){
    	if ( !a.len ) return b;
    	node res;
    	res.len = a.len + b.len;
    	res.pre = a.pre , res.suf = b.suf; //pre和suf中包含了长度1..n-1的所有信息,所以合并的时候直接&就好
    	res.num = a.num + b.num;
    	if ( a.len <= n - 2 ) res.pre &= (b.pre >> a.len) | (all << (n - 1 - a.len)); 
    	if ( b.len <= n - 2 ) res.suf &= (a.suf << b.len) | (all >> (n - 1 - b.len));
    	if ( res.len >= n ){
    		bitset<N> tmp = a.suf & b.pre;
    		if ( a.len <= n - 2 ) tmp &= all >> (n - 1 - a.len); //如果a的长度不足,则删除高位
    		if ( b.len <= n - 2 ) tmp &= all << (n - 1 - b.len); //删除低位
    		res.num += tmp.count();
    	}
    	return res;
    }
    void init(){
    	pow_[0] = 1;
    	rep(i,1,64) pow_[i] = pow_[i - 1] * d;
    
    	int c = 0;
    	while ( pow_[c + 1] < r ) c++;
    	rep(i,1,n - 1) all[i] = 1;
    	rep(j,0,m){
    		f[0][j].len = 1;
    		if ( n == 1 ) f[0][j].num = j <= B[1];
    		else{
    			//把没有出现的位置看成0
    			//这样便于合并、否则每次合并还需要check整段是否合法
    			rep(k,1,n){
    				f[0][j].pre[k - 1] = j <= B[k];
    				f[0][j].suf[k] = j <= B[k];
    			}
    		}
    	}
    	rep(i,1,c){
    		rep(j,0,m){
    			rep(k,0,d - 1){
    				f[i][j] = merge(f[i][j],f[i - 1][(j + gen[k]) % m]);
    			}
    		}
    	}
    }
    ll solve(ll n){
    	int c = 0;
    	while ( pow_[c + 1] < n ) c++;
    	int add = 0; node res;
    	repd(i,c,0){
    		rep(j,0,d - 1){
    			if ( n >= pow_[i] ){
    				n -= pow_[i];
    				res = merge(res,f[i][(gen[j] + add) % m]);
    			}
    			else{
    				add += gen[j];
    				break;
    			}
    		}
    	}
    	cout<<res.num<<endl;
    	return res.num;
    }
    int main(){
    	scanf("%d %d",&d,&m);
    	rep(i,0,d - 1) scanf("%d",&gen[i]);
    	scanf("%d",&n);
    	rep(i,1,n) scanf("%d",&B[i]);
    	cin>>l>>r;
    	init();
    	cout<<solve(r) - solve(l + n - 2)<<endl;
    }
    

    题外话

    降智...

  • 相关阅读:
    window 编译lua 5.3
    邮件服务器软件
    mkyaffs2image 生成不了120M的镜像文件的解决方法
    C static struct
    uboot 如何向内核传递参数
    linux 链接理解
    snmp 协议之理解
    交叉编译知识点总结
    回滚原理 Since database connections are thread-local, this is thread-safe.
    REST 架构的替代方案 为什么说GraphQL是API的未来?
  • 原文地址:https://www.cnblogs.com/Grice/p/12897983.html
Copyright © 2011-2022 走看看