• 21杭电多校第十场


    C

    注意到最后一段连续的可行答案其实很长

    记录一下对于每个(i)来说最后一段连续的起始位置然后暴力转移

    #include<bits/stdc++.h>
    #define inf 2139062143
    #define ll long long
    #define db double
    #define ld long double
    #define ull unsigned long long
    #define MAXN 1001001
    #define MOD 998244353
    #define Fill(a,x) memset(a,x,sizeof(a))
    #define rep(i,s,t) for(int i=(s),i##end=(t);i<=i##end;++i)
    #define dwn(i,s,t) for(int i=(s),i##end=(t);i>=i##end;--i)
    #define ren for(int i=fst[x];i;i=nxt[i])
    #define pls(a,b) (a+b)%MOD
    #define mns(a,b) (a-(b))%MOD
    #define mul(a,b) (1LL*(a)*(b))%MOD
    #define pii pair<int,int>
    #define fi first
    #define se second
    #define pb push_back
    using namespace std;
    inline int read()
    {
        int x=0,f=1;char ch=getchar();
        while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
        while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    int vis[MAXN],las[MAXN];
    vector<int> ans[750];
    int main()
    {
    	ans[1].pb(0);
    	rep(i,2,700)
    	{
    		ans[i].pb(0);las[i]=las[i-1]+i-1;
    		rep(j,1,i-1) for(auto x:ans[j]) if(!vis[x+j*(i-j)]&&(x+j*(i-j)<=las[i]))
    			{ans[i].pb(x+j*(i-j));vis[x+j*(i-j)]=1;}
    		sort(ans[i].begin(),ans[i].end());
    		dwn(j,ans[i].size()-1,0)
    			if(j==ans[i].size()-1||ans[i][j]+1==ans[i][j+1]) las[i]=ans[i][j];
    			else break;
    		for(auto x:ans[i]) vis[x]=0;
    	}
    	rep(T,1,read())
    	{
    		int n=read();
    		for(auto x:ans[n]) if(x>las[n]) break;else printf("%d ",x);
    		rep(i,las[n]+1,n*(n-1)/2) printf("%d%c",i,i==n*(n-1)/2?'
    ':' ');
    	}
    }
    

    D

    朴素的容斥复杂度为(O(T2^{16}))无法通过

    由于前(8)个质数的积(lim)很小,可以预处理出([1,lim])中所有数是否是前(8)个质数的倍数

    对于一个数(n)来说,令(f_n)表示(le n)的数中不是前八个质数倍数的数的个数,则(f_n=lfloorfrac{n}{lim} floorcdot f_{lim}+f_{n\%lim})

    因此只需要在此基础上容斥后(k-8)个质数即可

    #include<bits/stdc++.h>
    #define inf 2139062143
    #define ll long long
    #define db double
    #define ld long double
    #define ull unsigned long long
    #define MAXN 10010010
    #define MOD 998244353
    #define Fill(a,x) memset(a,x,sizeof(a))
    #define rep(i,s,t) for(int i=(s),i##end=(t);i<=i##end;++i)
    #define dwn(i,s,t) for(int i=(s),i##end=(t);i>=i##end;--i)
    #define ren for(int i=fst[x];i;i=nxt[i])
    #define pls(a,b) (a+b)%MOD
    #define mns(a,b) (a-(b))%MOD
    #define mul(a,b) (1LL*(a)*(b))%MOD
    #define pii pair<int,int>
    #define fi first
    #define se second
    #define pb push_back
    using namespace std;
    inline ll read()
    {
        ll x=0,f=1;char ch=getchar();
        while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
        while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    const int lim=9699690;
    int f[MAXN],k;ll n,ans;
    int p[20]={2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53};
    void mem(int n=lim) 
    {
    	rep(i,0,7) for(int j=p[i];j<=lim;j+=p[i]) f[j]=1;
    	rep(i,1,lim-1) f[i]=f[i-1]+(1-f[i]);
    }
    inline ll calc(ll n)
    {
    	return n/lim*f[lim-1]+f[n%lim];
    }
    int main()
    {
    	mem();int mxs,val;ll now;
    	rep(T,1,read())
    	{
    		n=read(),k=read();ans=0;
    		if(k<=8) 
    		{
    			mxs=(1<<k)-1;
    			rep(i,0,mxs)
    			{
    				now=val=1;
    				rep(j,0,k-1) if((i>>j)&1) now*=p[j],val=-val;
    				ans+=n/now*val;
    			}
    		}
    		else
    		{
    			mxs=(1<<k-8)-1;
    			rep(i,0,mxs)
    			{
    				now=val=1;
    				rep(j,0,k-1) if((i>>j)&1) now*=p[j+8],val=-val;
    				ans+=calc(n/now)*val;
    			}
    		}
    		printf("%lld
    ",ans);
    	}
    }
    

    H

    问题即为有多少个位置(i)满足(s[1:x])(s[1:i])的后缀且(s[n-y+1:n])(s[i+1:n])的前缀

    即询问有多少个前缀满足前缀(x)是它的后缀,建出(kmp)树之后相当于求多少个(i)(x)的子树内

    后缀同理,问题转化为二维数点问题,横坐标为前缀(i)在前缀(kmp)树的(dfs)序,纵坐标为后缀(i+1)在后缀(kmp)树中的

    每次查询为一个矩形,用主席树可以解决

    #include<bits/stdc++.h>
    #define inf 2139062143
    #define ll long long
    #define db double
    #define ld long double
    #define ull unsigned long long
    #define MAXN 200100
    #define MOD 998244353
    #define Fill(a,x) memset(a,x,sizeof(a))
    #define rep(i,s,t) for(int i=(s),i##end=(t);i<=i##end;++i)
    #define dwn(i,s,t) for(int i=(s),i##end=(t);i>=i##end;--i)
    #define ren for(int i=fst[x];i;i=nxt[i])
    #define pls(a,b) (a+b)%MOD
    #define mns(a,b) (a-(b))%MOD
    #define mul(a,b) (1LL*(a)*(b))%MOD
    #define pii pair<int,int>
    #define fi first
    #define se second
    #define pb push_back
    using namespace std;
    inline int read()
    {
        int x=0,f=1;char ch=getchar();
        while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
        while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    int n,q,g[MAXN],nxt[MAXN],in[MAXN][2],ou[MAXN][2],dfn;
    int rt[MAXN],w[MAXN<<6],ls[MAXN<<6],rs[MAXN<<6],tot;
    vector<int> G[MAXN];
    char s[MAXN];
    void dfs(int x,int t)
    {
    	if(x) in[!t?x:n+1-x][t]=++dfn;
    	for(auto v:G[x]) dfs(v,t);
    	if(x) ou[!t?x:n+1-x][t]=dfn;
    }
    void kmp(int t)
    {
    	int j=0;rep(i,2,n)
    	{
    		while(j&&s[j+1]!=s[i]) j=nxt[j];
    		if(s[j+1]==s[i]) j++;nxt[i]=j;
    	}
    	rep(i,0,n) G[i].clear();
    	rep(i,1,n) G[nxt[i]].pb(i);
    	dfn=0;dfs(0,t);
    }
    bool cmp(int x,int y){return in[x][0]<in[y][0];}
    void mdf(int &k,int kk,int l,int r,int x)
    {
    	w[k=++tot]=w[kk]+1,ls[k]=ls[kk],rs[k]=rs[kk];
    	if(l==r) return ;int mid=l+r>>1;
    	x<=mid?mdf(ls[k],ls[kk],l,mid,x):mdf(rs[k],rs[kk],mid+1,r,x);
    }
    int query(int k,int kk,int l,int r,int a,int b)
    {
    	if(!k) return 0;if(a<=l&&r<=b) return w[k]-w[kk];
    	int mid=l+r>>1,res=0;
    	if(a<=mid) res=query(ls[k],ls[kk],l,mid,a,b);
    	if(b>mid) res+=query(rs[k],rs[kk],mid+1,r,a,b);
    	return res;
    }
    inline void buildt()
    {
    	rep(i,1,n) g[i]=i;
    	sort(g+1,g+n+1,cmp);
    	rep(i,1,n)
    		if(g[i]==n) rt[i]=rt[i-1];
    		else mdf(rt[i],rt[i-1],1,n,in[g[i]+1][1]);
    }
    int main()
    {
    	int x,y;rep(T,1,read()) 
    	{
    		n=read(),q=read();scanf("%s",s+1);
    		kmp(0);rep(i,1,n>>1) swap(s[i],s[n+1-i]);
    		kmp(1);buildt();
    		while(q--)
    		{
    			x=read(),y=read(),y=n+1-y;
    			printf("%d
    ",query(rt[ou[x][0]],rt[in[x][0]-1],1,n,in[y][1],ou[y][1]));
    		}
    		for(;tot;tot--) ls[tot]=rs[tot]=w[tot]=0;
    	}
    }
    
  • 相关阅读:
    redis/memcached可视化客户端工具TreeNMS
    Navicat Mysql快捷键
    mysql全文索引之模糊查询
    Discuz网警过滤关键词库
    php中的implements 使用详解
    PHP 依赖注入和控制反转再谈(二)
    php 中的closure用法
    C# 反射(Reflection)技术
    Oracle pl/sql编程值控制结构
    Oracle PL/SQL编程之变量
  • 原文地址:https://www.cnblogs.com/yyc-jack-0920/p/15166539.html
Copyright © 2020-2023  润新知