D1T1 - 数学计算
直接用线段树/平衡树维护所有数的积即可。我思想僵化写了一个数学方法...应该是能做\(\bmod\)所有数的乘除法。
时间复杂度\(O(nlogn)\)。
D1T2 - 智力竞赛
二分答案+最小可相交路径覆盖。题意有点乱...
D1T3 - party
Icefox orz 是我不会的DDP呢。首先列出最长公共子序列的DP方程,\(dp[i][j]\)表示\(a_1\)的前\(i\)位与\(a_2\)的前\(j\)位的LCS长度:
\[ dp[i][j]=max(dp[i-1][j],dp[i][j-1],dp[i-1][j-1]+[a_1[i]=a_2[j]]) \] 观察到\(dp[i][j]\)只会比\(dp[i][j-1]\)大0/1,所以将这个DP数组压成一个二进制数进行DP。\(f[i][s]\)表示对于一个长度为\(i\)的兑奖串,此时的DP数组的状态为\(s\)时的方案数。预处理出DP数组根据第\(i\)位的选择会转移到什么状态,就可以做啦。由于要求不能出现“NOI”所以再加一维记录前两位的状态就好啦。
时间复杂度\(O(n2^k)\)。
D2T1 - str
\(dp[i][j]\)表示用了前\(i\)种串,在位置\(j\)匹配结束的串的个数。那么对于第\(i+1\)种串用KMP得到其能匹配在哪些位置,就可以转移到\(dp[i+1]\)了。
时间复杂度\(O(|s|\Sigma a)\)。
D2T2 - xor
基本是个可持久化trie树裸题。不过好像Windows下DFS会爆栈?
时间复杂度\(O(n+30Q)\)。
D3T3 - 教科书般的亵渎
玩过炉石的应该很容易看懂题。再加上我最近经常玩变节咆哮魔亵渎术233
最终目标是求\(S(n,k)=\sum_{i=1}^n i^k\)。有两种方法:
\[\begin{align*} (n+1)^{k+1}-n^{k+1} &= \binom{k+1}{1}n^k+\binom{k+1}{2}n^{k-1}+...+\binom{k+1}{k+1}n^0 \\ n^{k+1}-(n-1)^{k+1} &= \binom{k+1}{1}(n-1)^k+\binom{k+1}{2}(n-1)^{k-1}+...+\binom{k+1}{k+1}(n-1)^0 \\ &... \\ 2^{k+1}-1^{k+1} &= \binom{k+1}{1}1^k+\binom{k+1}{2}1^{k-1}+...+\binom{k+1}{k+1}1^0 \\ \end{align*}\] 相加,得
\[\begin{align*} (n+1)^{k+1}-1 &= \binom{k+1}{1}S(n,k)+\binom{k+1}{2}S(n,k-1)+...+\binom{k+1}{k+1}S(n,0) \\ S(n,k) &= \frac{1}{k+1}((n+1)^{k+1}-\sum_{i=2}^{k+1}\binom{k+1}{i}S(n,k+1-i)-1) \end{align*}\] 于是我们就可以在\(O(k^2)\)的时间内求出\(S(n,k)\)。
另一种做法是利用伯努利数。
首先有
\[ S(n,k)= \frac{1}{k+1} \sum_{i=1}^{k+1}\binom{k+1}{i}B_{k+1-i}(n+1)^i \]其中\(B\)是伯努利数,伯努利数满足\(B_0=1\),对于\(n>0\)有
\[ \sum_{i=0}^{n}\binom{n+1}{i}B_i=0 \] 然后就可以求了。不要问我为什么,我也不知道!
Code
D1T1
#include <cstdio>
typedef long long lint;
inline char gc()
{
static char now[1<<16],*s,*t;
if(s==t) {t=(s=now)+fread(now,1,1<<16,stdin); if(s==t) return EOF;}
return *s++;
}
inline int read()
{
int x=0; char ch=gc();
while(ch<'0'||'9'<ch) ch=gc();
while('0'<=ch&&ch<='9') x=x*10+ch-'0',ch=gc();
return x;
}
const int N=1e4+10;
const int N1=1e5+10;
int cntP,pr[N1]; bool notP[N1];
int p1[N1],phi[N1];
void init()
{
phi[1]=1;
for(lint i=2;i<=1e5;i++)
{
if(!notP[i])
{
pr[++cntP]=i; p1[i]=i,phi[i]=i-1;
for(lint j=i*i;j<=1e5;j*=i) p1[j]=j,phi[j]=(i-1)*(j/i);
}
for(int j=1;j<=cntP;j++)
{
if(i*pr[j]>1e5) break;
int x=i*pr[j]; notP[x]=true;
if(i%pr[j]) p1[x]=pr[j],phi[x]=phi[i]*(pr[j]-1);
else {p1[x]=p1[i]*pr[j],phi[x]=phi[p1[x]]*phi[x/p1[x]]; break;}
}
}
}
int pow(int x,int y,int P)
{
while(x<0) x+=P;
lint r=1,t=x;
for(int i=y;i;i>>=1,t=t*t%P) if(i&1) r=r*t%P;
return r;
}
int cnt,p[N],q[N]; lint m[N],a[N],k[N];
int getX()
{
int a1=0,m1=1,phi1=1;
for(int i=1;i<=cnt;i++)
{
int m2=m[i],a2=(k[i]>=q[i])?0:(a[i]*pow(p[i],k[i],m[i]));
int phi2=(p[i]-1)*(m[i]/p[i]);
lint t=1LL*a1*m2-1LL*a2*m1;
while(t<0) t+=m1*m2;
a1=t*pow(m2-m1,phi1*phi2-1,m1*m2)%(m1*m2);
m1=m1*m2; phi1=phi1*phi2;
}
return a1;
}
int pos[N1];
void work0(int Q,int P)
{
int ans=1;
for(int owo=1;owo<=Q;owo++)
{
int opt=read(),x=read();
pos[owo]=x;
if(opt==1) ans=(lint)ans*x%P;
else ans=(lint)ans*pow(pos[x],P-2,P)%P;
printf("%d\n",ans);
}
}
int main()
{
freopen("cal.in","r",stdin);
freopen("cal.out","w",stdout);
int task=read(); init();
while(task--)
{
int Q=read(),mod=read();
cnt=0;
for(int i=1,t=mod;i<=cntP+1;i++)
{
if(i==cntP+1&&t>1)
{
cnt++,p[cnt]=t,q[cnt]=1,m[cnt]=t,a[cnt]=1,k[cnt]=0;
break;
}
if(t<pr[i]) break;
if(t%pr[i]==0) cnt++,p[cnt]=pr[i],q[cnt]=0,m[cnt]=1,a[cnt]=1,k[cnt]=0;
while(t%pr[i]==0) t/=pr[i],q[cnt]++,m[cnt]*=pr[i];
}
if(cnt<=1) {work0(Q,mod); continue;}
for(int owo=1;owo<=Q;owo++)
{
int opt=read(),x=read();
pos[owo]=x;
if(opt==1)
{
for(int i=1;i<=cnt;i++)
{
int t=x;
while(t%p[i]==0) t/=p[i],k[i]++;
a[i]=(lint)a[i]*t%m[i];
}
}
else
{
for(int i=1;i<=cnt;i++)
{
int t=pos[x];
while(t%p[i]==0) t/=p[i],k[i]--;
a[i]=(lint)a[i]*pow(t,(p[i]-1)*(m[i]/p[i])-1,m[i])%m[i];
}
}
//for(int i=1;i<=cnt;i++) printf("=%d (mod %d) k=%d\n",a[i],m[i],k[i]);
printf("%d\n",getX());
}
}
return 0;
}
D1T2
//智力竞赛
#include <algorithm>
#include <cstdio>
#include <cstring>
using std::sort;
inline char gc()
{
static char now[1<<16],*s,*t;
if(s==t) {t=(s=now)+fread(now,1,1<<16,stdin); if(s==t) return EOF;}
return *s++;
}
inline int read()
{
int x=0; char ch=gc();
while(ch<'0'||'9'<ch) ch=gc();
while('0'<=ch&&ch<='9') x=x*10+ch-'0',ch=gc();
return x;
}
const int N=600;
int n,m,w[N]; bool ed[N][N],e[N][N];
int map[N];
struct rec{int w,id;} r[N];
bool cmpW(rec x,rec y) {return x.w<y.w;}
int n1; int link[N]; bool used[N];
bool find(int u)
{
for(int v=1;v<=n1;v++)
{
if(!e[u][v]||used[v]) continue;
used[v]=true;
if(!link[v]||find(link[v])) {link[v]=u; return true;}
}
return false;
}
int match()
{
int res=0; memset(link,0,sizeof link);
for(int u=1;u<=n1;u++)
{
memset(used,0,sizeof used);
if(find(u)) res++;
}
return res;
}
bool check(int x)
{
n1=x;
memset(e,false,sizeof e);
for(int u=1;u<=n1;u++)
for(int v=1;v<=n1;v++)
e[u][v]=ed[u][v];
for(int k=1;k<=n1;k++)
for(int u=1;u<=n1;u++)
for(int v=1;v<=n1;v++)
e[u][v]|=e[u][k]&&e[k][v];
return n1-match()<=m;
}
int main()
{
freopen("contest.in","r",stdin);
freopen("contest.out","w",stdout);
m=read()+1,n=read();
for(int i=1;i<=n;i++)
{
r[i].w=read(),r[i].id=i; int x=read();
for(int j=1;j<=x;j++) e[i][read()]=true;
}
sort(r+1,r+n+1,cmpW);
for(int i=1;i<=n;i++) w[i]=r[i].w,map[r[i].id]=i;
for(int u=1;u<=n;u++)
for(int v=1;v<=n;v++) if(e[u][v]) ed[map[u]][map[v]]=true;
int L=1,R=n;
while(L<=R)
{
int mid=L+R>>1;
if(check(mid)) L=mid+1;
else R=mid-1;
}
if(R<n) printf("%d\n",r[R+1].w);
else puts("AK");
return 0;
}
D1T3
//party
#include <cstdio>
#include <cstring>
inline int max(int x,int y) {return x>y?x:y;}
const int S=1<<16;
const int P=1e9+7;
int n,m,U; char s0[20];
int tr1[S][3],tr2[3][3];
int f1[20],f2[20];
int getDP(int x)
{
for(int i=1;i<=m;i++)
f2[i]=max(f1[i-1]+(x==s0[i]),max(f1[i],f2[i-1]));
int s=0;
for(int i=1;i<=m;i++) s|=(f2[i]-f2[i-1])<<i-1;
return s;
}
int dp[2][S][4];
int bitcnt(int s) {int r=0; while(s) r+=s&1,s>>=1; return r;}
int ans[20];
int main()
{
freopen("party.in","r",stdin);
freopen("party.out","w",stdout);
scanf("%d%d",&n,&m); scanf("%s",s0+1);
for(int i=1;i<=m;i++)
if(s0[i]=='N') s0[i]=0;
else if(s0[i]=='O') s0[i]=1;
else s0[i]=2;
U=(1<<m)-1;
for(int s=0;s<=U;s++)
{
for(int i=1;i<=m;i++) f1[i]=f1[i-1]+((s>>i-1)&1);
for(int k=0;k<3;k++) tr1[s][k]=getDP(k);
}
tr2[0][0]=1;
tr2[1][0]=1,tr2[1][1]=2;
tr2[2][0]=1,tr2[2][2]=3;
int c=0; dp[c][0][0]=1;
for(int i=1;i<=n;i++)
{
c^=1;
for(int s1=0;s1<=U;s1++)
for(int s2=0;s2<3;s2++)
for(int k=0;k<3;k++)
dp[c][tr1[s1][k]][tr2[s2][k]]+=dp[c^1][s1][s2],dp[c][tr1[s1][k]][tr2[s2][k]]%=P;
memset(dp[c^1],0,sizeof dp[c^1]);
}
for(int s=0;s<=U;s++) ans[bitcnt(s)]=((long long)ans[bitcnt(s)]+dp[c][s][0]+dp[c][s][1]+dp[c][s][2])%P;
for(int i=0;i<=m;i++) printf("%d\n",ans[i]);
return 0;
}
D2T1
//str
#include <cstdio>
#include <cstring>
const int N=1e4+10;
const int P=1e9+7;
int n,k; char s[N],s0[30];
int f[2][N];
int nxt[30];
void getNxt(char s[])
{
int len=strlen(s+1);
nxt[0]=nxt[1]=0;
for(int i=2;i<=len;i++)
{
int j=nxt[i-1];
while(j&&s[i]!=s[j+1]) j=nxt[j];
if(s[i]==s[j+1]) nxt[i]=j+1;
else nxt[i]=0;
}
}
int main()
{
freopen("str.in","r",stdin);
freopen("str.out","w",stdout);
scanf("%d",&k);
scanf("%s",s+1),n=strlen(s+1);
int c=0;
for(int i=0;i<=n;i++) f[c][i]=1;
for(int owo=0;owo<k;owo++,c^=1)
{
memset(f[c^1],0,sizeof f[c^1]);
int cnt; scanf("%d",&cnt);
while(cnt--)
{
scanf("%s",s0+1); getNxt(s0);
int len=strlen(s0+1);
for(int i=1,j=0;i<=n;i++)
{
while(j&&s[i]!=s0[j+1]) j=nxt[j];
if(s[i]==s0[j+1]) j++;
if(j==len) f[c^1][i]=(f[c^1][i]+f[c][i-len])%P;
}
}
}
int ans=0;
for(int i=0;i<=n;i++) ans=(ans+f[c][i])%P;
printf("%d\n",ans);
return 0;
}
D2T2
//xor
#include <algorithm>
#include <cstdio>
using namespace std;
inline char gc()
{
static char now[1<<16],*s,*t;
if(s==t) {t=(s=now)+fread(now,1,1<<16,stdin); if(s==t) return EOF;}
return *s++;
}
inline int read()
{
int x=0; char ch=gc();
while(ch<'0'||'9'<ch) ch=gc();
while('0'<=ch&&ch<='9') x=x*10+ch-'0',ch=gc();
return x;
}
const int N=1e5+10;
int n,w[N];
int edCnt,h[N];
struct edge{int v,nxt;} ed[N<<1];
void edAdd(int u,int v)
{
edCnt++; ed[edCnt].v=v,ed[edCnt].nxt=h[u],h[u]=edCnt;
edCnt++; ed[edCnt].v=u,ed[edCnt].nxt=h[v],h[v]=edCnt;
}
int fa[N][20],dpt[N];
int dfCnt,dfn[N],fr[N],to[N];
void dfs(int u)
{
dfn[++dfCnt]=u; fr[u]=dfCnt;
for(int k=1;k<=17;k++) fa[u][k]=fa[fa[u][k-1]][k-1];
for(int i=h[u];i;i=ed[i].nxt)
{
int v=ed[i].v;
if(v==fa[u][0]) continue;
fa[v][0]=u,dpt[v]=dpt[u]+1,dfs(v);
}
to[u]=dfCnt;
}
inline lca(int u,int v)
{
if(dpt[u]<dpt[v]) swap(u,v);
for(int k=17;k>=0;k--) if(dpt[fa[u][k]]>=dpt[v]) u=fa[u][k];
if(u==v) return u;
for(int k=17;k>=0;k--) if(fa[u][k]!=fa[v][k]) u=fa[u][k],v=fa[v][k];
return fa[u][0];
}
const int N1=N*31;
int rt1[N],rt2[N];
int ndCnt,ch[N1][2],siz[N1];
inline void ndCopy(int p,int &q) {ch[p][0]=ch[q][0],ch[p][1]=ch[q][1],siz[p]=siz[q];}
void ins(int &p,int x,int d)
{
ndCopy(++ndCnt,p);
p=ndCnt; siz[p]++;
if(d<0) return;
int t=(x>>d)&1;
ins(ch[p][t],x,d-1);
}
void bldTr2(int u)
{
ins(rt2[u]=rt2[fa[u][0]],w[u],30);
for(int i=h[u];i;i=ed[i].nxt)
{
int v=ed[i].v;
if(v!=fa[u][0]) bldTr2(v);
}
}
int qres;
void query1(int p1,int p2,int x)
{
int now=0;
for(int d=30;d>=0;d--)
{
int t=((x>>d)&1)^1,sizT=siz[ch[p2][t]]-siz[ch[p1][t]];
if(!sizT) t^=1;
p1=ch[p1][t],p2=ch[p2][t],now|=t<<d;
}
qres=x^now;
}
void query2(int p1,int p2,int p3,int x)
{
int now=0;
for(int d=30;d>=0;d--)
{
int t=((x>>d)&1)^1,sizT=siz[ch[p1][t]]+siz[ch[p2][t]]-siz[ch[p3][t]]*2;
if(!sizT) t^=1;
p1=ch[p1][t],p2=ch[p2][t],p3=ch[p3][t],now|=t<<d;
}
qres=x^now;
}
void show(int p)
{
if(!p) return;
printf("%2d siz=%d ch=%d,%d\n",p,siz[p],ch[p][0],ch[p][1]);
show(ch[p][0]); show(ch[p][1]);
}
int main()
{
freopen("xor.in","r",stdin);
freopen("xor.out","w",stdout);
n=read(); int Q=read();
for(int i=1;i<=n;i++) w[i]=read();
for(int i=1;i<=n-1;i++)
{
int u=read(),v=read();
edAdd(u,v);
}
fa[1][0]=0,dpt[1]=1,dfs(1);
for(int i=1;i<=n;i++) ins(rt1[i]=rt1[i-1],w[dfn[i]],30);
bldTr2(1);
/*for(int i=1;i<=n;i++) show(rt1[i]),puts("");
puts("");
for(int i=1;i<=n;i++) show(rt2[i]),puts("");*/
while(Q--)
{
int opt=read();
if(opt==1)
{
int u=read(),x=read();
qres=0; query1(rt1[fr[u]-1],rt1[to[u]],x);
}
else
{
int u=read(),v=read(),x=read();
int t=lca(u,v);
qres=0; query2(rt2[u],rt2[v],rt2[t],x);
qres=max(qres,w[t]^x);
}
printf("%d\n",qres);
}
return 0;
}
D2T3
//教科书般的亵渎
#include <algorithm>
#include <cstdio>
using std::sort;
typedef long long lint;
inline lint read()
{
lint x=0; char ch=getchar();
while(ch<'0'||'9'<ch) ch=getchar();
while('0'<=ch&&ch<='9') x=x*10+ch-'0',ch=getchar();
return x;
}
const int P=1e9+7;
const int M=60;
lint n,a[M]; int m;
int B[M],C[M][M],inv[M];
void init(int n)
{
inv[1]=1;
for(int i=2;i<=n;i++) inv[i]=1LL*inv[P%i]*(P-P/i)%P;
for(int i=0;i<=n;i++)
{
C[i][0]=1;
for(int j=1;j<=i;j++) C[i][j]=(C[i-1][j-1]+C[i-1][j])%P;
}
B[0]=1;
for(int i=1;i<=n-1;i++)
{
B[i]=0;
for(int j=0;j<=i-1;j++) B[i]=(B[i]+1LL*C[i+1][j]*B[j])%P;
B[i]=(1LL*(P-B[i])*inv[i+1])%P;
}
}
int pow(lint x,int y)
{
lint r=1,t=x;
for(int i=y;i;i>>=1,t=t*t%P) if(i&1) r=r*t%P;
return r;
}
int S(lint n)
{
int s=0;
for(int i=1;i<=m+1;i++) s=(s+1LL*C[m+1][i]*B[m+1-i]%P*pow(n+1,i)%P)%P;
s=1LL*s*inv[m+1]%P;
//printf("Sigma(%d,%d)=%d\n",n,m,s);
return s;
}
int main()
{
freopen("defile.in","r",stdin);
freopen("defile.out","w",stdout);
init(59);
int task=read();
while(task--)
{
n=read(),m=read();
for(int i=1;i<=m;i++) a[i]=read();
a[++m]=++n; sort(a+1,a+m+1);
lint ans=0;
for(int i=1;i<=m;i++)
{
for(int j=i;j<=m;j++) ans=(ans+S(a[j]-1)-S(a[j-1])+P)%P;
for(int j=i+1;j<=m;j++) a[j]-=a[i]; a[i]=0;
}
printf("%lld\n",ans);
}
return 0;
}