省選模擬22
阿新 • • 發佈:2022-03-04
剛考完學考下午就考試了,好像這個題都挺簡單??
最終我只有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;
}