2021.8.19考試總結[NOIP模擬44]
阿新 • • 發佈:2021-08-20
T1Emotional_flutter T2Medium_counting T3Huge_counting T4字元消除2
T1 emotional flutter
把腳長合到黑條中。
每個黑條可以對映到統一區間,實際操作就是左右端點取模。長度大於$k$時顯然不合法。
然後檢查一遍區間內有沒有不被黑條覆蓋的點即可。
區間端點處理屬實$ex$
$code:$
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long LL; 4 5 namespace IO{ 6 inline int read(){ 7 int x=0,f=1; char ch=getchar(); 8 whileT1(ch<'0'||ch>'9'){ if(ch=='-') f=-1; ch=getchar(); } 9 while(ch>='0'&&ch<='9'){ x=(x<<1)+(x<<3)+(ch^48); ch=getchar(); } 10 return x*f; 11 } 12 inline void write(int x,char sp){ 13 char ch[20]; int len=0; 14 if(x<0){ putchar('-'); x=~x+1; } 15 do{ ch[len++]=x%10+(1<<5)+(1<<4); x/=10; }while(x); 16 for(int i=len-1;~i;i--) putchar(ch[i]); putchar(sp); 17 } 18 } using namespace IO; 19 20 const int NN=5e5+5; 21 int t,n,cnt; 22 LL a[NN],d[NN],s,k,step,mx; 23 bool skip,win; 24 struct black{ LL l,r; }b[NN]; 25inline bool cmp(black x,black y){ return x.l==y.l?x.r<y.r:x.l<y.l; } 26 27 signed main(){ 28 t=read(); 29 while(t--){ 30 s=read(); k=read(); n=read(); cnt=0; skip=0; mx=0; win=0; 31 for(int i=1;i<=n;i++) 32 a[i]=read(), d[i]=d[i-1]+a[i]; 33 for(int i=1;i<=n;i+=2){ 34 int l=(d[i-1]+1)%k,r=(d[i]+s-1)%k; 35 if(d[i]+s-d[i-1]-2>=k){ skip=1; break; } 36 if(l<=r) b[++cnt]=(black){l,r}; 37 else b[++cnt]=(black){0,r}, b[++cnt]=(black){l,k-1}; 38 } 39 if(skip){ puts("NIE"); continue; } 40 sort(b+1,b+cnt+1,cmp); 41 if(b[1].l) win=1; 42 for(int i=1;i<=cnt;i++){ 43 if(mx+1<b[i].l){ win=1; break; } 44 mx=max(mx,b[i].r); 45 } 46 if(mx<k-1) win=1; 47 puts(win?"TAK":"NIE"); 48 } 49 return 0; 50 }
T2 medium counting
神仙$DP$。
設$f_{l,r,i,c}$表示只考慮$l$到$r$的串,強制讓它們前$i$位相等,且第$i$位至少是$c$的方案。
轉移時列舉$l$與$r$之間的一個串$i$。
不知道該說什麼,太神仙了
$code:$
1 #include<bits/stdc++.h> 2 #define int long long 3 #define rin register signed 4 using namespace std; 5 6 namespace IO{ 7 inline int read(){ 8 int x=0,f=1; char ch=getchar(); 9 while(ch<'0'||ch>'9'){ if(ch=='-') f=-1; ch=getchar(); } 10 while(ch>='0'&&ch<='9'){ x=(x<<1)+(x<<3)+(ch^48); ch=getchar(); } 11 return x*f; 12 } 13 inline void write(int x,char sp){ 14 char ch[20]; int len=0; 15 if(x<0){ putchar('-'); x=~x+1; } 16 do{ ch[len++]=x%10+(1<<5)+(1<<4); x/=10; }while(x); 17 for(rin i=len-1;~i;i--) putchar(ch[i]); putchar(sp); 18 } 19 } using namespace IO; 20 21 const int p=990804011; 22 int n,mxl,f[60][60][30][30],len[60],a[60][30]; 23 char ch[60][30]; 24 25 int dfs(int l,int r,int pos,int c){ 26 if(l>r) return f[l][r][pos][c]=1; 27 if(~f[l][r][pos][c]) return f[l][r][pos][c]; 28 if(pos>mxl) return f[l][r][pos][c]=(l==r); 29 if(c>26) return f[l][r][pos][c]=0; 30 f[l][r][pos][c]=dfs(l,r,pos,c+1); 31 for(rin i=l;i<=r;i++){ 32 if(!(a[i][pos]==c||(c&&a[i][pos]==27))) break; 33 (f[l][r][pos][c]+=dfs(l,i,pos+1,0)*dfs(i+1,r,pos,c+1)%p)%=p; 34 } 35 return f[l][r][pos][c]; 36 } 37 38 signed main(){ 39 n=read(); memset(f,-1,sizeof(f)); 40 for(rin i=1;i<=n;i++){ 41 scanf("%s",ch[i]+1); 42 len[i]=strlen(ch[i]+1); 43 mxl=max(len[i],mxl); 44 for(rin j=1;j<=len[i];j++) 45 a[i][j]=(ch[i][j]=='?')?27:(ch[i][j]-'a'+1); 46 } 47 write(dfs(1,n,1,0),'\n'); 48 return 0; 49 }T2
T3 huge counting
一個函式的實際貢獻只於將它所有引數減到$1$的方案數奇偶性有關。
多重集排列:$\frac{\sum{x_i}!}{\prod{x_i!}}$