暑期集训8
rank 12 mark 140
(括号中均是题目名称不是我的评价)
T1【出了个大阴间题】状压DP;
T2【T2 最简单辣快来做】平面二维坐标系问题前缀和思想处理;
T3【T3 是我的你不要抢 】hash/kmp水暴力正解AC自动机
T4【T4显然也是我出的】裴蜀定理应用:见数论--裴蜀定理
T1给你n个有序点对(ai,bi),对其进行全排列,规定合并规则是从左到右以此22合并。a=(ai==aj)ai+1/max(ai,aj),b=2max(bi,bj)+1,cost=ka+bi+bj。(n<=18,a<=1e9)
40tps:直接枚举全排列
80tps:对于n<=10,全排列,对于a<=n,dp[i][j]表示已经选择的集合是i,当前a是j的合并总费用。cnt[i][j]数组辅助当前状态被多少状态更新过来,ber[i][j]辅助记录当前的b是多少。O(\(2^n *n*max(ai+1)\))
点击查看代码
const int N=0;const ll mod=1e9+7;
int n;
ll k,ai[25],ar[25],bi[25];int A[25];
int dp[263000][90];
int ber[263000][90],cnt[263000][90];
inline ll calc(ll a,ll b1,ll b2)
{
//chu("a:%lld b:%lld\n",a,b1);
return ((ll)a*k%mod*b2%mod+(ll)b1)%mod;
}
#define lowbit(x) (x&(-x))
inline ll calc2(ll a,ll b1,ll b2)
{
return (a*k%mod+b1+b2)%mod;
}
inline void deal()
{
_f(i,1,n){ar[i]=re();A[i]=i;}
//只要都不重复那方案唯一,就是全排列的算法,但是b还是要模拟.....
ll mxa=0;
do
{
_f(i,1,n)ai[i]=ar[i];
_f(i,2,n)//now deal:ai[A[i]] and update bi
{
int op1=A[i-1],op2=A[i];
ai[op2]=(ai[op1]==ai[op2])?(ai[op1]+1):(max(ai[op1],ai[op2]));
//chu("ai[%d]:%d\n",op2,ai[op2]);
}
mxa=max(mxa,ai[A[n]]);
}while(next_permutation(A+1,A+1+n));
_f(i,1,n)A[i]=i;
ll tot=0;
do
{
_f(i,1,n)ai[i]=ar[i],bi[i]=0;ll nowtot=0;
_f(i,2,n)//now deal:ai[A[i]] and update bi
{
int op1=A[i-1],op2=A[i];
ai[op2]=(ai[op1]==ai[op2])?(ai[op1]+1):(max(ai[op1],ai[op2]));
nowtot=(nowtot+calc2(ai[op2],bi[op1],bi[op2]))%mod;
bi[op2]=2*max(bi[op1],bi[op2])+1;
}
if(ai[A[n]]==mxa)tot=(tot+nowtot)%mod;
}while(next_permutation(A+1,A+1+n));
chu("%lld %lld",mxa,tot);
}
signed main()
{
freopen("repair.in","r",stdin);
freopen("repair.out","w",stdout);
n=re(),k=re();
if(n<=10)
{
deal();return 0;
}
_f(i,1,n)ai[i]=re();
int mx_bhav=(1<<n)-1;
_f(i,0,mx_bhav)
_f(j,0,n+1)dp[i][j]=-1;
dp[0][0]=0;int mx_a=n+1;
_f(i,0,n-1)
{
dp[1<<i][ai[i+1]]=0;//没有花费,b是0
ber[1<<i][ai[i+1]]=0;
cnt[1<<i][ai[i+1]]=1;
}
_f(i,1,mx_bhav)//初始更新完毕
{
_f(j,0,mx_a)//
{
if(dp[i][j]==-1)continue;
_f(k,1,n)
{
if((1<<(k-1))&i)continue;
ll mya=((j==ai[k])?(j+1):max((ll)j,ai[k]));
// chu("j:%d ai[%d]:%d mya:%d\n",j,k,ai[k],mya);
// if(i==2&&j==1)
// {
// chu("from %d update:choose:%d,mxa=:%d\n",i,k,j);
// chu("dp[%d][%d]:%d\n",i,j,dp[i][j]);
// chu("update:%d %d\n",i|(1<<(k-1)),mya);
// }
if(dp[i|(1<<(k-1))][mya]!=-1)
dp[i|(1<<(k-1))][mya]=((ll)dp[i|(1<<(k-1))][mya]+(ll)dp[i][j]+(ll)calc(mya,ber[i][j],cnt[i][j]))%mod;//这个维护的是费用
else
dp[i|(1<<(k-1))][mya]=((ll)dp[i][j]+(ll)calc(mya,(ll)ber[i][j],(ll)cnt[i][j]))%mod;
// chu("dev:%d %d\n",calc(mya,ber[i][j],cnt[i][j]),dp[i|(1<<(k-1))][mya]);
cnt[i|(1<<(k-1))][mya]=((ll)cnt[i|(1<<(k-1))][mya]+(ll)cnt[i][j])%mod;
ber[i|(1<<(k-1))][mya]=((ll)ber[i|(1<<(k-1))][mya]+(ll)2*ber[i][j]+(ll)cnt[i][j])%mod;
}
}
}
int pos=0;
// _f(i,1,mx_bhav)
// {
// _f(j,1,n)chu("状态:%d a的值是%d,累计花费:%lld,b是:%d(update:%d)\n",i,j,dp[i][j],ber[i][j],cnt[i][j]);
// }
f_(i,mx_a,0)
if(dp[mx_bhav][i]!=-1)
{
chu("%d %d",i,dp[mx_bhav][i]);break;
}//等会儿
return 0;
}
点击查看代码
int n,ker;
int dp[263000][2],g[263000][2],num[263000],mx[263000],a[25];
#define lowbit(x) (x&(-x))
int main()
{
freopen("repair.in","r",stdin);
freopen("repair.out","w",stdout);
n=re(),ker=re();
int mx_b=(1<<n)-1;
_f(i,1,n)a[i]=re();
_f(i,1,mx_b)
{
_f(j,1,n)
{
if(i&(1<<(j-1)))
{
mx[i]=max(mx[i],a[j]);
num[i]++;
}
if((i-lowbit(i))==0)g[i][0]=1;
}
}
_f(i,1,mx_b)
{
_f(j,0,1)
{
_f(k,1,n)
{
if(i&(1<<(k-1)))continue;
ll mxa=(((j+mx[i])==a[k])?(a[k]+1):max(j+mx[i],a[k]));
ll goal=(i|(1<<(k-1)));
ll code=mxa-mx[goal];
dp[goal][code]=((ll)dp[goal][code]+(ll)dp[i][j]+(ll)g[i][j]*((ll)mxa*ker%mod+1LL*((1<<(num[i]-1))-1)%mod)%mod)%mod;
g[goal][code]=((ll)g[goal][code]+(ll)g[i][j])%mod;
}
}
}
if(g[mx_b][1])chu("%d %d",mx[mx_b]+1,dp[mx_b][1]);
else chu("%d %d",mx[mx_b],dp[mx_b][0]);
return 0;
}
T2:三维空间,有n个点对(xi,yi,hi),给你多组(pi,qi),对于每个(pi,qi),ans=$hi*a^{abs(xi-pi)} * b^{abs(yi-qi)} $.(n<=2000,hi,xi,yi<=1e9)
正解100tps:以(x,y)为中间点,sum[x][y][0/1/2]分别预处理出4个平面方向的点对对(x,y)的贡献。在查询答案的时候,我们直接找到离已经处理的关键点最近的位置,分别加上4个方向的所有点对的贡献,还要乘上多余出来的距离(因为(x,y)不一定出现在离散化的坐标中)。
代码
const int block=50000,maxn=2000;
int n,q;ll mod,a,b;
int x[maxn+100],y[maxn+100],fx[maxn+100],fy[maxn+100],h[maxn+100];//离散化和数组下标
ll ra[block+100],rb[block+100],bsa[block+100],bsb[block+100];
ll sum[maxn+10][maxn+10][4];//怕空间炸
inline ll powa(ll zhi){return ra[zhi/block]*bsa[zhi%block]%mod;}
inline ll powb(ll zhi){return rb[zhi/block]*bsb[zhi%block]%mod;}
inline void Prework()
{
bsa[0]=bsb[0]=ra[0]=rb[0]=1;
_f(i,1,block)bsa[i]=bsa[i-1]*a%mod,bsb[i]=bsb[i-1]*b%mod;
_f(i,1,block)ra[i]=ra[i-1]*bsa[block]%mod,rb[i]=rb[i-1]*bsb[block]%mod;//这是光速幂
sort(fx+1,fx+1+n);sort(fy+1,fy+1+n);
_f(i,1,n)
{
x[i]=lower_bound(fx+1,fx+1+n,x[i])-fx;y[i]=lower_bound(fy+1,fy+1+n,y[i])-fy;
sum[x[i]][y[i]][0]=sum[x[i]][y[i]][1]=sum[x[i]][y[i]][2]=sum[x[i]][y[i]][3]=h[i];
}
_f(i,1,n)
{
_f(j,1,n)
sum[i][j][0]=(sum[i][j][0]+sum[i][j-1][0]*powb(fy[j]-fy[j-1])%mod)%mod;
_f(j,1,n)
sum[i][j][0]=(sum[i][j][0]+sum[i-1][j][0]*powa(fx[i]-fx[i-1])%mod)%mod;
f_(j,n,1)
sum[i][j][1]=(sum[i][j][1]+sum[i][j+1][1]*powb(fy[j+1]-fy[j])%mod)%mod;
f_(j,n,1)
sum[i][j][1]=(sum[i][j][1]+sum[i-1][j][1]*powa(fx[i]-fx[i-1])%mod)%mod;
}
f_(i,n,1)
{
_f(j,1,n)
sum[i][j][2]=(sum[i][j][2]+sum[i][j-1][2]*powb(fy[j]-fy[j-1])%mod)%mod;
f_(j,n,1)
sum[i][j][2]=(sum[i][j][2]+sum[i+1][j][2]*powa(fx[i+1]-fx[i])%mod)%mod;
f_(j,n,1)
sum[i][j][3]=(sum[i][j][3]+sum[i][j+1][3]*powb(fy[j+1]-fy[j])%mod)%mod;
f_(j,n,1)
sum[i][j][3]=(sum[i][j][3]+sum[i+1][j][3]*powa(fx[i+1]-fx[i])%mod)%mod;
}//预处理完成!
}
inline ll Work(int px,int py)
{
int dx=lower_bound(fx+1,fx+1+n,px)-fx;
int dy=lower_bound(fy+1,fy+1+n,py)-fy;
ll res=0;
if(dx-1&&dy-1)
res=(res+sum[dx-1][dy-1][0]*powa(px-fx[dx-1])%mod*powb(py-fy[dy-1])%mod)%mod;
if(dx-1&&dy<=n)
res=(res+sum[dx-1][dy][1]*powa(px-fx[dx-1])%mod*powb(fy[dy]-py)%mod)%mod;
if(dx<=n&&dy-1)
res=(res+sum[dx][dy-1][2]*powa(fx[dx]-px)%mod*powb(py-fy[dy-1])%mod)%mod;
if(dx<=n&&dy<=n)
res=(res+sum[dx][dy][3]*powa(fx[dx]-px)%mod*powb(fy[dy]-py)%mod)%mod;
return res;
}
int main()
{
freopen("satellite.in","r",stdin);
freopen("satellite.out","w",stdout);
n=re(),q=re();re();re();
mod=re();a=re();b=re();
_f(i,1,n)h[i]=re(),x[i]=fx[i]=re(),y[i]=fy[i]=re();
Prework();
_f(i,1,q)
{
int per=re(),qer=re();chu("%lld\n",Work(per,qer));
}
return 0;
}
点击查看代码
const int N = 2010, M = 6.4e4 + 10;
int n, q, W, H, mod;
ll a, b, A[M], B[M];
int x[N], y[N];
ll h[N];
void into()
{
A[0] = B[0] = 1;
for (re int i = 1; i <= 32000; ++i)
A[i] = A[i - 1] * a % mod, B[i] = B[i - 1] * b % mod;
for (re int i = 32001; i <= 64000; ++i)
A[i] = A[i - 1] * A[32000] % mod, B[i] = B[i - 1] * B[32000] % mod;
}
ll query(int s1, int s2)
{
if(s1 >= 32000 && s2 >= 32000) return A[s1 % 32000] * A[s1 / 32000 + 32000 - 1] % mod * B[s2 % 32000] % mod * B[s2 / 32000 + 32000 - 1] % mod;
if(s1 >= 32000) return A[s1 % 32000] * A[s1 / 32000 + 32000 - 1] % mod * B[s2] % mod;
if(s2 >= 32000) return A[s1] * B[s2 % 32000] % mod * B[s2 / 32000 + 32000 - 1] % mod;
return A[s1] * B[s2] % mod;
}
int Abs(int x) { return x >= 0 ? x : ~x + 1; }
int main()
{
freopen("satellite.in", "r", stdin);
freopen("satellite.out", "w", stdout);
n = read(), q = read(), W = read(), H = read(), mod = read(), a = read(), b = read();
for (re int i = 1; i <= n; ++i)
h[i] = read(), x[i] = read(), y[i] = read();
into();
while (q--)
{
int s1 = read(), s2 = read();
ll ans = 0;
for (re int i = 1; i <= n; ++i)
ans += h[i] * query(Abs(x[i] - s1), Abs(y[i] - s2)) % mod;
printf ("%lld\n", ans % mod);
}
return 0;
}
T3:给你n个字符串(length<=6e5),给出q组询问(q<=1e6),每组询问2个参数(x,y)表示询问x串前缀和y串后缀最长匹配长度。
hash(1)记忆化,对于重复的mod串和txt串记录答案(2)贪心,对于匹配从大到小,找到就跳
点击查看代码
#include<iostream>
#include<cstdio>
#include<ctime>
#include<cmath>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<bitset>
#include<deque>
#include<queue>
#include<vector>
#include<set>
#include<map>
#include<iomanip>
using namespace std;
#define _f(i,a,b) for(register int i=a;i<=b;++i)
#define f_(i,a,b) for(register int i=a;i>=b;--i)
#define ll long long
#define ull unsigned long long
#define chu printf
#define rint register int
inline ll re()
{
ll x=0,h=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')h=-1;ch=getchar();}
while(ch<='9'&&ch>='0'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
return x*h;
}
const int N=6e5;const ull code=131;
int n,q;
vector<int>pre[N+100];
vector<ull>g[N+100];
map<int,int>mp[N+100];int len[N+100];
ull po[N+100];
inline ull gethash(int co,int l,int r)
{
return g[co][r]-g[co][l-1]*po[r-l+1];
}
int main()
{
freopen("string.in","r",stdin);
freopen("string.out","w",stdout);
n=re(),q=re();
char s[N];int mxleln=0;
_f(i,1,n)
{
scanf("%s",s+1);g[i].push_back(0);pre[i].push_back(0);
len[i]=strlen(s+1);mxleln=max(mxleln,len[i]);
_f(j,1,len[i])
{
pre[i].push_back(s[j]-'a'+1);g[i].push_back(g[i][j-1]*code+pre[i][j]);
}
}
po[0]=1;
_f(i,1,mxleln)po[i]=po[i-1]*code;
_f(dfdsf,1,q)
{
int y=re(),x=re();
if(mp[x].find(y)!=mp[x].end())
{
// chu("mem\n");
chu("%d\n",mp[x][y]);continue;
}
int milen=min(len[x],len[y]);int ans=0;
f_(i,milen,1)
{
if(gethash(x,1,i)==gethash(y,len[y]-i+1,len[y])){ans=i;break;}
}
mp[x][y]=ans;
chu("%d\n",ans);
}
return 0;
}
/*
3 6
wwq
eew
qwe
1 2
2 3
1 3
2 1
3 2
3 1
*/
浙公网安备 33010602011771号