1. 程式人生 > 其它 >2021.8.19考試總結[NOIP模擬44]

2021.8.19考試總結[NOIP模擬44]

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         while
(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]; 25
inline 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 }
T1

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!}}$