省选模拟24
刚考完学考下午就考试了,好像这个题都挺简单??
最终我只有70分,还挺不甘心的,最后仍然是发现自己的思路方向本身就有问题,还是能力的欠缺!
可能经过这么长时间的训练,最后提升的是代码能力,思维能力还是很差......
T1 排队
虽然很快就找到了dp方程,但是无法用矩阵优化,甚至写出了拉格朗日插值发现不是一个多项式...
根据模数很小这个东西,我们可以造出1000个矩阵,然后转移
也可以对答案找循环节!!
当然还有一个可以直接用矩阵优化的方程!!
设dp[i][j][k]表示当前放了前i大的数,有j段,有k个不好的点
我们从大到小依次加入,一个点可以单独形成一个段,也可以接在某一个段的两侧,也可以用来合并两个段
最后要的是dp[n][1][m],这样保证了你钦定为不好的点一定是不好的点,因为合并只能用更小的合并,于是这个东西两侧一定比他小
转移很简单,可以用矩阵乘优化
AC_code
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define fo(i,x,y) for(int i=(x);i<=(y);i++)
#define fu(i,x,y) for(int i=(x);i>=(y);i--)
int read(){
int s=0,t=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')t=-1;ch=getchar();}
while(isdigit(ch)){s=s*10+ch-'0';ch=getchar();}
return s*t;
}
const int N=1e6+5;
const int M=105;
int n,m,p;
struct matrix{
int x[M][M];
matrix(){memset(x,0,sizeof(x));}
matrix operator * (matrix a)const{
matrix ret;
fo(i,1,m*m)fo(k,1,m*m)if(x[i][k])fo(j,1,m*m)ret.x[i][j]=(ret.x[i][j]+x[i][k]*a.x[k][j])%p;
return ret;
}
}ma,xs;
int id(int x,int y){return (x-1)*m+y;}
signed main(){
freopen("queue.in","r",stdin);
freopen("queue.out","w",stdout);
n=read();m=read();p=read();
fo(i,1,m)fo(j,1,m){
if(i!=m&&j!=m)xs.x[id(i,j)][id(i+1,j+1)]=i+1;
if(i>1)xs.x[id(i,j)][id(i-1,j)]=i-1;
xs.x[id(i,j)][id(i,j)]=i<<1;
}
ma.x[1][id(1,1)]=1;n--;
while(n){
if(n&1)ma=ma*xs;
xs=xs*xs;n>>=1;
}
printf("%lld",ma.x[1][id(1,m)]);
return 0;
}
T2 昵称
考场上费劲心思想预处理一些东西,最后一个一个直接填,于是写的非常麻烦!!
其实到这里的时候就可以停下来了,科学追求的是简洁而又正确,如果过于麻烦,就可以放弃这个思路了
于是我们可以通过简单的数位dp得到当前的方案数!!
我们记忆化一下这样复杂度就对了
AC_code
#include<bits/stdc++.h>
using namespace std;
#define int __int128
#define ll long long
#define fo(i,x,y) for(int i=(x);i<=(y);i++)
#define fu(i,x,y) for(int i=(x);i>=(y);i--)
int read(){
int s=0,t=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')t=-1;ch=getchar();}
while(isdigit(ch)){s=s*10+ch-'0';ch=getchar();}
return s*t;
}
const int N=1055;
char a[N];int n,len,m,s[N];
int ksm(int x,int y){
int ret=1;
while(y){
if(y&1)ret=ret*x;
x=x*x;y>>=1;
}return ret;
}
int dp[N][N],f[N];
bool jud(int ln,int &lim){
int tmp=lim;lim-=ksm(10,ln);
if(lim<=0){lim=tmp;return true;}
fo(i,2,ln+1){
lim-=f[i-1]*ksm(10,ln-i+1);
if(lim<=0){lim=tmp;return true;}
}return false;
}
int nxt[N],fail[N][15];
int g[N][N][2];
int dfs(int x,int y,int t){
if(x==m){
if(t)return 0;
else return 1;
}
if(~g[x][y][t])return g[x][y][t];
int ret=0;fo(i,0,9)ret+=dfs(x+1,fail[y][i],t&(fail[y][i]!=len));
//cerr<<(ll)x<<" "<<(ll)y<<" "<<(ll)t<<endl;
return g[x][y][t]=ret;
}
signed main(){
freopen("nickname.in","r",stdin);
freopen("nickname.out","w",stdout);
scanf("%s",a+1);len=strlen(a+1);n=read();
fo(i,1,len)s[i]=a[i]-'0';
for(int i=2,j=0;i<=len;i++){
while(j&&s[i]!=s[j+1])j=nxt[j];
if(s[i]==s[j+1])j++;nxt[i]=j;
}
fo(i,0,len){
fo(j,0,9)fail[i][j]=fail[nxt[i]][j];
if(i!=len)fail[i][s[i+1]]=i+1;
}
fo(i,1,9){
if(i==s[1])dp[1][1]++;
else dp[1][0]++;
}
fo(i,1,18)fo(j,0,len-1){
if(!dp[i][j])continue;
fo(k,0,9)dp[i+1][fail[j][k]]+=dp[i][j];
}
fo(i,1,18){
fo(j,0,len-1)f[i]+=dp[i][j];
int now=nxt[len];
while(now)f[i]-=dp[i][len-now],now=nxt[now];
}
m=0;while(!jud(m,n))m++;m+=len;
memset(g,-1,sizeof(g));
int now=0,fl=1;
fo(i,1,m){
fo(j,0,9){
if(i==1&&j==0)continue;
int res=dfs(i,fail[now][j],fl&(fail[now][j]!=len));
//cerr<<(ll)i<<" "<<(ll)fail[now][j]<<" "<<(ll)res<<endl;
if(n<=res){
now=fail[now][j];
if(now==len)fl=0;
printf("%lld",(ll)j);
break;
}n-=res;
}
// cerr<<(ll)i<<endl;
}
return 0;
}
T3 帝国防卫
考场上甚至没有来得及看这个题
发现最多更改\(log^2\)层,于是我们用深度颗线段树来解决这个东西
每一个点只会变得小于零一次,一旦发现小于零了,那就直接搜下去
AC_code
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define fo(i,x,y) for(int i=(x);i<=(y);i++)
#define fu(i,x,y) for(int i=(x);i>=(y);i--)
int read(){
int s=0,t=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')t=-1;ch=getchar();}
while(isdigit(ch)){s=s*10+ch-'0';ch=getchar();}
return s*t;
}
const int N=1e5+5;
const int inf=0x3f3f3f3f3f3f3f3f;
int n,m;
struct BIT{
int tr[N];
void ins(int x){
//cout<<"ins"<<" "<<x<<endl;
for(int i=x;i<=n;i+=(i&-i))tr[i]++;
}
int query(int x){
int ret=0;
for(int i=x;i;i-=(i&-i))ret+=tr[i];
return ret;
}
int qry(int l,int r){
return query(r)-query(l-1);
}
}bit;
struct XDS{
int rt[N];
struct POT{
int ls,rs;
int mn,tg;
}tr[N*35];
int seg;
XDS(){tr[0].mn=inf;}
int newpot(){return ++seg;}
void pushup(int x){
tr[x].mn=min(tr[tr[x].ls].mn,tr[tr[x].rs].mn);
return ;
}
void pushdown(int x){
if(tr[x].ls){
tr[tr[x].ls].mn+=tr[x].tg;
tr[tr[x].ls].tg+=tr[x].tg;
}
if(tr[x].rs){
tr[tr[x].rs].mn+=tr[x].tg;
tr[tr[x].rs].tg+=tr[x].tg;
}
tr[x].tg=0;
}
void chg(int x,int l,int r){
if(l==r)return tr[x].mn=inf,bit.ins(l),void();
int mid=l+r>>1;if(tr[x].tg)pushdown(x);
if(tr[tr[x].ls].mn<=0)chg(tr[x].ls,l,mid);
if(tr[tr[x].rs].mn<=0)chg(tr[x].rs,mid+1,r);
pushup(x);return ;
}
void ins(int &x,int l,int r,int ql,int qr,int v){
if(ql>qr)return ;
if(!x)x=newpot();
if(ql<=l&&r<=qr){
tr[x].mn+=v;tr[x].tg+=v;
if(tr[x].mn<=0)chg(x,l,r);
return ;
}
int mid=l+r>>1;if(tr[x].tg)pushdown(x);
if(ql<=mid&&(tr[x].ls||v>0))ins(tr[x].ls,l,mid,ql,qr,v);
if(qr>mid&&(tr[x].rs||v>0))ins(tr[x].rs,mid+1,r,ql,qr,v);
pushup(x);return ;
}
}xds;
int c[N];
struct E{int to,nxt;}e[N*2];
int head[N],rp;
void add_edg(int x,int y){
e[++rp].to=y;e[rp].nxt=head[x];head[x]=rp;
}
int dfn[N],dfm[N],cnt,dep[N],fa[N];
void dfs(int x,int f,int d){
dfn[x]=++cnt;dep[x]=d;fa[x]=f;
xds.ins(xds.rt[d],1,n,dfn[x],dfn[x],c[x]);
for(int i=head[x];i;i=e[i].nxt){
int y=e[i].to;
if(y==f)continue;
dfs(y,x,d+1);
}dfm[x]=cnt;
}
signed main(){
freopen("empire.in","r",stdin);
freopen("empire.out","w",stdout);
n=read();
fo(i,1,n)c[i]=read();
fo(i,1,n-1){
int x=read(),y=read();
add_edg(x,y);add_edg(y,x);
}
dfs(1,0,1);
m=read();
while(m--){
int tp,x,a,now;
tp=read();
if(tp==1){
x=read();a=read();
for(int i=dep[x],na=a;na;i++,na>>=1)xds.ins(xds.rt[i],1,n,dfn[x],dfm[x],-na);
now=fa[x];a>>=1;
while(now&&a){
for(int i=dep[now],na=a;na;i++,na>>=1){
xds.ins(xds.rt[i],1,n,dfn[now],dfn[x]-1,-na);
xds.ins(xds.rt[i],1,n,dfm[x]+1,dfm[now],-na);
}x=now;now=fa[now];a>>=1;
}
}
if(tp==2){
x=read();
printf("%lld\n",bit.qry(dfn[x],dfm[x]));
}
}
return 0;
}
QQ:2953174821

浙公网安备 33010602011771号