【T1】congruence
数学题
在只有一块的情况下,答案为
pk−(p−1)k−1
其中k为单一块的大小
对于几个块的情况考虑dp
dp[i][j]表示做第 i 块
≡
j 的方案总数
可以想到线性的递推代替之
代码如下:
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
int mod;
inline void rd(int& x)
{
static char ch;
for (;!isdigit(ch=getchar()););
for (x=ch-48;isdigit(ch=getchar());x=x*10+ch-48);
}
inline int pw(int x,int y)
{
int rt=1;
for (;y;y>>=1,x=x*(LL)x%mod)
if (y&1) rt=rt*(LL)x%mod;
return rt;
}
inline void solve(void)
{
int n,p,x,ans,tot,t;
rd(n);rd(x);rd(p);rd(mod);
ans=!x;tot=1;
for (int i=1;i<=n;++i)
{
rd(x);t=pw(p,x);
ans=(ans*(LL)t+pw(p-1,x-1)*(LL)(tot-p*(LL)ans%mod))%mod;
tot=tot*(LL)t%mod;
}
printf("%d\n",(ans+mod)%mod);
}
int main()
{
freopen("congruence.in","r",stdin);
freopen("congruence.out","w",stdout);
int t;
for (rd(t);t--;) solve();
return 0;
}
【T2】 permutation
首先是一个合唱队形的问题,蛇形排列棒的要死
然后排个序离散化,各种分类讨论
排列时左端点为X1,右端点为X2
X1 != X2 只有一种放法
X1 = X2 根据字典序再讨论一下
大概就是这样
简直被恶心死,看代码吧
#include <bits/stdc++.h>
using namespace std;
const int N=100000+5;
int n,m,l,r,v[N],q[N],num[N],L[N],R[N],ans[N];
inline void rd(int& x)
{
static char ch;
for (;!isdigit(ch=getchar()););
for (x=ch-48;isdigit(ch=getchar());x=x*10+ch-48);
}
inline bool cmp(const int& x,const int& y){return v[x]<v[y] ||(v[x]==v[y] && x<y);}
inline void solve(void)
{
rd(n);m=0;l=0;r=n+1;
for (int i=1;i<=n;++i) rd(v[i]),q[i]=i;
sort(q+1,q+n+1,cmp);
for (int i=1,j;i<=n;i=j)
{
L[++m]=i;num[m]=v[q[i]];
for (j=i;j<=n && v[q[j]]==v[q[i]];++j);
R[m]=j-1;
}
ans[r]=0;
for (int i=1;i<=m;)
{
if (L[i]>R[i] && ++i>m) break;
if (v[ans[l]]<v[ans[r]]) ans[++l]=q[L[i]++];else
if (v[ans[l]]>v[ans[r]]) ans[--r]=q[R[i]--];else
if (num[i]==v[ans[l]])
{
if ((i+1<=m && q[L[i+1]]<q[L[i]])||(i+2<=m && L[i+1]==R[i+1] && q[L[i+2]]<q[L[i]]))
while (R[i]>=L[i]) ans[--r]=q[R[i]--];
else ans[++l]=q[L[i]++];
}else{
if (i+1<=m && L[i]==R[i] && q[L[i+1]]<q[L[i]])
ans[--r]=q[R[i]--];
else ans[++l]=q[L[i]++];
}
}
for (int i=1;i<=n;++i) printf("%d%c",ans[i]," \n"[i==n]);
}
int main()
{
freopen("permutation.in","r",stdin);
freopen("permutation.out","w",stdout);
int t;
for (rd(t);t--;) solve();
return 0;
}
【T3】recursion
Fibonacci数列前n项和:
Sn=Fn+2
知道这个大概会容易一点
部分分还是很好拿的
100%套一个矩阵乘法
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N=40+3;
const int L=N*2;
const int mod=1000000009;
int n,m,l,f[L][L],g[L][L],rt[L][L],t[L][L],v[L],w[L];
inline void rd(int& x)
{
static char ch;
static bool flag;
for (flag=0;!isdigit(ch=getchar());flag=(ch=='-'));
for (x=ch-48;isdigit(ch=getchar());x=x*10+ch-48);
if (flag) x=-x;
}
inline void mul(int x)
{
for (int i=0;i<l;++i)
for (int j=0;j<l;++j)
rt[i][j]=(i==j),g[i][j]=f[i][j];
while (x)
{
if (x&1)
{
for (int i=0;i<l;++i)
for (int j=0;j<l;++j)
t[i][j]=rt[i][j],rt[i][j]=0;
for (int i=0;i<l;++i)
for (int k=0;k<l;++k)
if (t[i][k])
for (int j=(k<m)?0:m;j<l;++j)
if (g[k][j])
rt[i][j]=(rt[i][j]+t[i][k]*(LL)g[k][j])%mod;
}
if ((x>>=1))
{
for (int i=0;i<l;++i)
for (int j=0;j<l;++j)
t[i][j]=g[i][j],g[i][j]=0;
for (int i=0;i<l;++i)
for (int k=0;k<l;++k)
if (t[i][k])
for (int j=(k<m)?0:m;j<l;++j)
if (t[k][j])
g[i][j]=(g[i][j]+t[i][k]*(LL)t[k][j])%mod;
}
}
}
int main()
{
freopen("recursion.in","r",stdin);
freopen("recursion.out","w",stdout);
rd(n);rd(m);l=m*2;
for (int i=1;i<=m;++i) rd(f[m-i][m-1]);
for (int i=0;i<m;++i) rd(v[i]);
for (int i=1;i<m;++i) f[i][i-1]=1;
for (int i=0;i<m;++i) f[i][m+i]=f[m+i][m+i]=1;
for (int i=1,x;i<=n;++i)
{
rd(x);mul(x);
for (int j=0;j<l;++j)
{
w[j]=0;
for (int k=0;k<l;++k)
w[j]=(w[j]+v[k]*(LL)rt[k][j])%mod;
}
for (int j=0;j<m;++j) v[j]=w[m+j];
}
printf("%d\n",(v[0]+mod)%mod);
return 0;
}
尾声
【你说的是人话吗?】
–【某智障不写题解我有什么办法?】
–【那你怎么还写了东西】
–【这些**他口述了半个小时!!!!!】