T1
经过打表发现f(x)=x (x>=2) f(1)=2;
然后问题就变为 ∑f(i)^k
拉格朗日插值法。。学习地址
#include <cstdio> #include <cctype> #define Mod 998244353 inline void read(register int &x) { register char ch=getchar(); for(x=0;!isdigit(ch);ch=getchar()); for(;isdigit(ch);x=x*10+ch-'0',ch=getchar()); } int l,r,k,ans; inline int ksm(register int a,register int b) { int r=1,base=a; for(;b;b>>=1,base=1ll*base*base%Mod) if(b&1) r=1ll*r*base%Mod; return r%Mod; } int main(int argc,char *argv[]) { freopen("count.in","r",stdin); freopen("count.out","w",stdout); scanf("%d%d%d",&l,&r,&k); for(register int i=l;i<=r;++i) { register int f; if(i==1||i==2) f=2; else f=i; ans=(ans%Mod+ksm(f,k))%Mod; } printf("%d ",ans); fclose(stdin); fclose(stdout); return 0; }
#include <cstring> #include <ctime> #include <cmath> #include <cstdio> #include <cstdlib> #include <iostream> #include <algorithm> using namespace std; const int Mod=998244353; const int MAXK=1000000; int power(int x,int k) { int ret=1; while (k) { if (k&1) ret=1LL*ret*x%Mod; x=1LL*x*x%Mod; k>>=1; } return ret; } int k; int f[MAXK+10]; int pre[MAXK+10],suf[MAXK+10]; int jc[MAXK+10],K[MAXK+10]; int cnt(int n) { if (n==0) return 0; int ans=0; if (n<=k+10 || n<=MAXK) { for (int i=1; i<=n; i++) ans=(K[i]+ans)%Mod; } else { pre[0]=1; for (int i=1; i<=k+2; i++) pre[i]=1LL*pre[i-1]*(n-i)%Mod; suf[k+3]=1; for (int i=k+2; i>=1; i--) suf[i]=1LL*suf[i+1]*(n-i)%Mod; int l=k+1,r=0,flag=((k+1)&1)?(-1):(1); for (int i=1; i<=k+2; i++) { int s=1LL*pre[i-1]*suf[i+1]%Mod,m=1LL*(flag*jc[l]+Mod)*jc[r]%Mod; ans=(1LL*f[i]*s%Mod*power(m,Mod-2)%Mod+ans)%Mod; l--; r++; flag*=-1; } } ans=((ans+K[2])%Mod-1+Mod)%Mod; return ans; } int L,R; void init() { cin>>L>>R>>k; for (int i=1; i<=MAXK+5; i++) K[i]=power(i,k); jc[0]=1; for (int i=1; i<=k+2; i++) jc[i]=1LL*jc[i-1]*i%Mod; for (int i=1; i<=k+2; i++) f[i]=(f[i-1]+K[i])%Mod; cout<<(cnt(R)-cnt(L-1)+Mod)%Mod; return ; } int main() { freopen("count.in","r",stdin); freopen("count.out","w",stdout); init(); fclose(stdin); fclose(stdout); //fprintf(stderr,"%.3lf ",1.0*clock()/(1.0*CLOCKS_PER_SEC)); return 0; }
T2
题意转化为求最大的区间长度使得这段区间和减k>=0
首先做前缀和,可知若当前到了k,i<j<k && sum[i]<sum[j]则j一定不可能比i更优
用单调栈维护这个过程。然后倒序更新答案即可。
#include<cstdlib> #include<cstdio> #include<cctype> #define N 1000005 typedef long long LL; int n,m,len,maxv,a[N]; LL sum[N]; inline void read(int &x) { register char ch=getchar(); for(x=0;!isdigit(ch);ch=getchar()); for(;isdigit(ch);x=x*10+ch-'0',ch=getchar()); } inline int max(int a,int b) {return a>b?a:b;} int main() { freopen("blocks.in","r",stdin); freopen("blocks.out","w",stdout); read(n);read(m); for(int i=1;i<=n;i++) { read(a[i]); sum[i]=sum[i-1]+a[i]; maxv=max(maxv,a[i]); } for(int k,i=1;i<=m;i++) { read(k); if(k>maxv) {i==m?printf("0 "):printf("0 ");continue;} for(register int l=1;l<=n;++l) for(register int r=l;r<=n;++r) { int tmp=r-l+1; if((sum[r]-sum[l-1]-tmp*k)>=0) len=max(len,tmp); } i==m?printf("%d ",len):printf("%d ",len);len=0; } fclose(stdin); fclose(stdout); return 0; }
#include<iostream> #include<cstdio> #include<cstring> #define N 1000007 using namespace std; long long sum[N]; int a[N],st[N],top,n,m,cnt; inline int read() { int x=0,f=1;char c=getchar(); while(c>'9'||c<'0'){if(c=='-')f=-1;c=getchar();} while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();} return x*f; } void solve(int k) { top=1;int res=0; for(int i=1;i<=n;i++) { sum[i]=sum[i-1]+a[i]-k; if(!top || sum[st[top]]>sum[i]) st[++top]=i; } for(int i=n;i>=1;i--) { while(top && sum[i]>=sum[st[top]]) top--; res=max(res,i-st[top+1]); } printf("%d ",res); } int main() { freopen("blocks.in","r",stdin); freopen("blocks.out","w",stdout); n=read();m=read(); for(int i=1;i<=n;i++) a[i]=read(); while(m--) solve(read()); return 0; }
T3
将字符串倒序插入trie树,问题就转换成了若干字符串结束的LCA深度
倍增维护LCA,每插入一个字符串,处理一次fa数组就可以了
当然这题也可以哈希+二分
#include <iostream> #include <cstring> #include <string> #include <cctype> #include <cstdio> #include <vector> #define N 50005 #define L 1000005 using namespace std; inline void read(int &x) { register char ch=getchar(); for(x=0;!isdigit(ch);ch=getchar()); for(;isdigit(ch);x=x*10+ch-'0',ch=getchar()); } int n,m,a[N],len[N]; string str[N]; inline int min(int a,int b) {return a>b?b:a;} int main(int argc,char *argv[]) { freopen("biology.in","r",stdin); freopen("biology.out","w",stdout); read(n);read(m); for(int i=1;i<=n;++i) cin>>str[i],len[i]=str[i].length(); for(register int opt,x;m--;) { read(opt); if(opt==1) cin>>str[++n],len[n]=str[n].length(); else { read(x); int limit=0x7fffffff; for(int i=1;i<=x;++i) read(a[i]),limit=min(limit,len[a[i]]); register int ans=limit; for(register int i=0;i<=limit;++i) { string s=str[a[1]]; register char ch=s[len[a[1]]-i-1]; bool flag=false; for(register int j=2;j<=x;++j) { string y=str[a[j]]; if(y[len[a[j]]-i-1]!=ch) { flag=true; break; } } if(flag) { ans=i; break; } } printf("%d ",ans); } } fclose(stdin); fclose(stdout); return 0; }
#include <cstring> #include <cstdio> #include <cctype> #define N 1000010 int n,m,tot=1,trie[N][28],dad[N][25],pos[N],dep[N]; char s[10005]; void ins(int num) { int p=1,l=strlen(s+1); for(int i=l;i;--i) { int id=s[i]-'a'; if(!trie[p][id]) { trie[p][id]=++tot; dep[tot]=dep[p]+1;dad[tot][0]=p; for(int j=1;j<=20;++j) dad[tot][j]=dad[dad[tot][j-1]][j-1]; } p=trie[p][id]; } pos[num]=p; } void swap(int &m,int &n) { int tmp=n; n=m; m=tmp; } int lca(int x,int y) { if(dep[x]>dep[y]) swap(x,y); for(int i=20;i>=0;--i) if(dep[dad[y][i]]>=dep[x]) y=dad[y][i]; if(x==y) return x; for(int i=20;i>=0;--i) if(dad[y][i]!=dad[x][i]) y=dad[y][i],x=dad[x][i]; return dad[x][0]; } int main(int argc,char *argv[]) { freopen("biology.in","r",stdin); freopen("biology.out","w",stdout); scanf("%d%d",&n,&m); dep[0]=-1; for(int i=1;i<=n;++i) scanf("%s",s+1),ins(i); for(int opt,x,y,v;m--;) { scanf("%d",&opt); if(opt==1) { scanf("%s",s+1); ins(++n); } else { scanf("%d%d",&x,&y); int z=pos[y]; for(int i=2;i<=x;++i) { scanf("%d",&v); z=lca(z,pos[v]); } printf("%d ",dep[z]); } } fclose(stdin); fclose(stdout); return 0; }
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> typedef unsigned long long ll; const int maxlen=1000005,maxn=150005,hpos=29; int n,m,S[maxn],T[maxn],len[maxn],nowlen,top,Stack[maxn]; char Arc[maxlen]; ll Hash[maxlen]; inline void read(int &now) { char Cget; now=0; while((Cget=getchar())>'9'||Cget<'0'); while(Cget>='0'&&Cget<='9') { now=now*10+Cget-'0'; Cget=getchar(); } } inline bool check(int lit) { ll tmp=Hash[T[Stack[1]]-lit+1]; for(int i=2;i<=top;i++) if(Hash[T[Stack[i]]-lit+1]!=tmp) return false; return true; } int main() { // freopen("data.txt","r",stdin); freopen("biology.in","r",stdin); freopen("biology.out","w",stdout); read(n); read(m); for(int i=1;i<=n;i++) { scanf("%s",Arc+nowlen); len[i]=strlen(Arc+nowlen); S[i]=nowlen; T[i]=nowlen+len[i]-1; nowlen+=len[i]; Hash[T[i]]=Arc[T[i]]-'a'+1; for(int v=T[i]-1;v>=S[i];v--) Hash[v]=Hash[v+1]*hpos+(Arc[v]-'a'+1); } for(int i=1,op,l,r,mid,res;i<=m;i++) { read(op); if(op==1) { ++n; scanf("%s",Arc+nowlen); len[n]=strlen(Arc+nowlen); S[n]=nowlen; T[n]=nowlen+len[n]-1; nowlen+=len[n]; Hash[T[n]]=Arc[T[n]]-'a'+1; for(int v=T[n]-1;v>=S[n];v--) Hash[v]=Hash[v+1]*hpos+(Arc[v]-'a'+1); } else { read(top); l=1,r=maxlen,mid,res=0; for(int v=1;v<=top;v++) { read(Stack[v]); r=std::min(r,len[Stack[v]]); } while(l<=r) { mid=l+r>>1; if(check(mid)) { res=mid; l=mid+1; } else r=mid-1; } printf("%d ",res); } } fclose(stdin); fclose(stdout); return 0; }