直接递归即可,稍微写个高精。
点击查看代码
#include<bits/stdc++.h>
using namespace std;
//#define int __int128
const int N=1e4;
string s;
int b[N],c[N],len;
int a[N],tot;
int read()
{
int f=1,s=0;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){s=(s<<1)+(s<<3)+(ch^48);ch=getchar();}
return f*s;
}
void dfs(int x,int m)
{
if(x<=1)
{
if(x==0) printf("2(0)");
if(x==1) printf("2");
return ;
}
int pos=m;
int d=1;
for(int i=1;i<=m;i++)
{
if(x&(d<<(i-1)))
{
pos=i;
break;
}
}
for(int i=m;i>=1;i--)
{
if(!(x&(d<<(i-1)))) continue;
if(i>2)
{
printf("2(");
}
int y=i,tot=0;
while(y) tot++,y=y>>1;
dfs(i-1,tot);
if(i>2)
{
printf(")");
}
if(i>pos) printf("+");
}
return ;
}
void chu()
{
for(int i=0;i<len;i++)
{
if(b[i]%2==0) b[i]/=2;
else b[i]/=2,b[i+1]=b[i+1]+10;
}
int tmp=len,cnt=0;
int flag=1;
for(int i=0;i<len;i++)
{
if(b[i]==0&&flag)
{
tmp--;
continue;
}
if(b[i]!=0) flag=0;
c[++cnt]=b[i];
}
len=tmp;
cnt=0;
for(int i=0;i<len;i++) b[i]=c[++cnt];
}
signed main()
{
freopen("pow.in","r",stdin);
freopen("pow.out","w",stdout);
cin>>s;
len=s.size();
for(int i=0;i<len;i++) b[i]=s[i]-'0';
while(len!=0)
{
a[++tot]=(b[len-1]&1);
chu();
}
int pos=tot;
for(int i=1;i<=tot;i++)
{
if(a[i]==1)
{
pos=i;
break;
}
}
for(int i=tot;i>=1;i--)
{
if(a[i]==0) continue;
if(i>2)
{
printf("2(");
}
int y=i,tot=0;
while(y) tot++,y=y>>1;
dfs(i-1,tot);
if(i>2)
{
printf(")");
}
if(i>pos) printf("+");
}
}
考虑二维前缀和直接容斥,再用 \(hash\) 优化一下复杂度。
点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define int unsigned long long
const int N=4e3+107;
int n,q;
int ans[N][N];
string s;
unordered_map<int,int>mp;
int cnt=0;
const int base=137;
int p[N],has[N];
int get_hash(int l,int r)
{
return has[r]-has[l-1]*p[r-l+1];
}
int read()
{
int f=1,s=0;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){s=(s<<1)+(s<<3)+(ch^48);ch=getchar();}
return f*s;
}
signed main()
{
freopen("substring.in","r",stdin);
freopen("substring.out","w",stdout);
n=read(),q=read();
cin>>s;s=' '+s;
p[0]=1;
for(int i=1;i<=n;i++) p[i]=p[i-1]*base;
for(int i=1;i<=n;i++) has[i]=has[i-1]*base+s[i];
for(int len=1;len<=n;len++)
{
mp.clear();
for(int l=1;l+len-1<=n;l++)
{
int r=l+len-1;
int tmp=get_hash(l,r);
ans[mp[tmp]][r]--;
mp[tmp]=l;
}
}
for(int l=n;l>=1;l--)
for(int r=l;r<=n;r++)
ans[l][r]+=ans[l+1][r]+ans[l][r-1]-ans[l+1][r-1]+1;
for(int i=1;i<=q;i++)
{
int l=read(),r=read();
printf("%lld\n",ans[l][r]);
}
}
正反分别建一颗trie树。直接看题解吧,挺详细的。
点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=3e5+107;
const int base=137;
string s[N];
int n,len[N];
bool flag[N],vis[N];
struct lmy
{
int n,tr[N][26];
int cnt[26];
void insert(string s,bool vis)
{
int rt=0,len=s.length();
if(!vis)
{
for(int i=0;i<len;i++)
{
int ch=s[i]-'a';
if(!tr[rt][ch]) tr[rt][ch]=++n;
rt=tr[rt][ch];
}
}
else
{
for(int i=len-1;i>=0;i--)
{
int ch=s[i]-'a';
if(!tr[rt][ch]) tr[rt][ch]=++n,++cnt[ch];
rt=tr[rt][ch];
}
}
}
}tr1,tr2;
int read()
{
int f=1,s=0;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){s=(s<<1)+(s<<3)+(ch^48);ch=getchar();}
return f*s;
}
signed main()
{
freopen("magic.in","r",stdin);
freopen("magic.out","w",stdout);
n=read();
tr1.n=tr2.n=0;
int ans=0;
for(int i=1;i<=n;i++)
{
cin>>s[i];
tr1.insert(s[i],0);
tr2.insert(s[i],1);
int len=s[i].length();
vis[s[i][len-1]-'a']=1;
if(len==1&&!flag[s[i][0]-'a']) ans++,flag[s[i][0]-'a']=1;
}
for(int i=1;i<=tr1.n;i++)
{
for(int x=0;x<26;x++)
{
if(!tr1.tr[i][x]) ans+=tr2.cnt[x];
else if(vis[x]) ans++;
}
}
printf("%lld\n",ans);
}