1. 程式人生 > >【模擬賽題解錦集】——Hzoi

【模擬賽題解錦集】——Hzoi

質數 spa else align can 11.2 == 問題 輔助

Day IXV:

  題目鏈接

  T1:

   對於二者之一$n$,每次選取要麽變成$2n$,要麽是$n-(tot-n)=2*n-tot$,即最後結果為$n*2^{k}(\mod tot)$.

  T2:

   思博題。枚舉每個右邊界$pos$,求其左邊界$l[pos]$,顯然其左邊界應該是$l[pos-1]$和最後一個滿足$a_{x}-K$為$a_{pos}$的倍數之間取一個較大值,然後用該數更新一下邊界位置即可。

  T3:

   其實DP是蠻裸的,可惜第一題浪費時間太久,最後半個小時想法已經很接近答案,但是也沒怎麽細想,這是今天最大的失誤。

   設$f_{i,j}$表示前$i$層已經選好且第$i$層恰好選取了$j$種顏色的全部方案,再設兩個輔助數組$g_{i,j},gc_{i,j}$。其中$g_{i,j}$表示長度為i的裝飾品,只使用確定的j種顏色的方案數,$gc$則表示任意j種顏色的方案數。

   然後我們很容易得到一個遞推式:$f_{i,j}=gc_{i,j}\sum_{x=1}^{a[i-1]}f_{i-1,x}-g_{i,j}f_{i-1,j}$。

   再考慮如何得到$g$和$gc$數組。考慮組合意義:$g_{i,j}=g_{i-1,j}(j-1)+g_{i-1,j-1}j$,$gc_{i,j}=g_{i,j}*(_{j}^{m})$。但是此題模數不保證為質數,所以組合數不好處理,換一種思路$gc_{i,j}=gc_{i-1,j}(j-1)+gc_{i-1,j-1}(m-j+1)$。

   然後就可以$O(max(a_{i})^2+S)$解決問題了。

代碼:

T1:

1 #include <cstdio>
2 int n,m,k,x=2;
3 int main(){
4     scanf("%d%d%d",&n,&m,&k),m=n+m;
5     for(;k;(k&1)?n=1ll*n*x%m:0,k>>=1,x=1ll*x*x%m);
6      printf("%d",n<m-n?n:m-n);
7 }

T2:

 1 #define Troy 10/14/2017
 2  
 3 #include <bits/stdc++.h>
 4  
 5
using namespace std; 6 7 inline int read(){ 8 int s=0,k=1;char ch=getchar(); 9 while(ch<0||ch>9) k=ch==-?-k:k,ch=getchar(); 10 while(ch>47&&ch<=9) s=s*10+(ch^48),ch=getchar(); 11 return s*k; 12 } 13 14 typedef long long ll; 15 16 const int N=1e5+7; 17 18 int n,k,a[N],l[N],r[N]; 19 int last[N]; 20 21 inline void add(int x,int pos){ 22 if(x<0) return ; 23 if(x==0){ 24 last[x]=pos; 25 return ; 26 } 27 for(int i=1;1ll*i*i<=x;i++){ 28 if(x%i==0) 29 last[i]=pos,last[x/i]=pos; 30 } 31 } 32 33 int main(){ 34 n=read(),k=read(); 35 for(int i=1;i<=n;i++) 36 a[i]=read(); 37 l[0]=1; 38 for(int i=1;i<=n;i++){ 39 if(a[i]>k) 40 l[i]=max(max(last[a[i]],last[0])+1,l[i-1]); 41 else 42 l[i]=l[i-1]; 43 add(a[i]-k,i); 44 } 45 ll ans=0; 46 for(int i=1;i<=n;i++) 47 ans=ans+(i-l[i]+1); 48 printf("%lld\n",ans); 49 }

T3:

 1 #define Troy 10/14/2017
 2 
 3 #include <cstdio>
 4 #include <vector>
 5 
 6 using namespace std;
 7 
 8 inline int read(){
 9     int s=0,k=1;char ch=getchar();
10     while(ch<0||ch>9)   k=ch==-?-k:k,ch=getchar();
11     while(ch>47&&ch<=9)   s=s*10+(ch^48),ch=getchar();
12     return s*k;
13 }
14 
15 typedef long long ll;
16 
17 const int N=5e3+7;
18 
19 int n,m,p,a[(int)1e6+7],f[2][N],gc[N][N],g[N][N];
20 
21 int main(){
22     n=read(),m=read(),p=read();
23     for(int i=1;i<=n;i++)
24         a[i]=read();
25     g[0][0]=1;
26     gc[0][0]=1;
27     for(int i=1;i<=5000;i++){     
28         for(int j=1;j<=min(i,m);j++){
29             g[i][j]=(1ll*g[i-1][j]*(j-1)+1ll*g[i-1][j-1]*j)%p,
30             gc[i][j]=(1ll*gc[i-1][j]*(j-1)%p+1ll*gc[i-1][j-1]*(m-j+1)%p)%p;
31         }    
32     }
33     f[0][0]=1;
34     int now=1,last=0;
35     for(int i=1;i<=n;i++){
36         for(int j=1;j<=a[i];j++){
37             f[now][j]=1ll*f[last][0]*gc[a[i]][j]%p;                        
38             if(a[i-1]>=j)
39                 f[now][j]-=1ll*f[last][j]*g[a[i]][j]%p;
40             f[now][j]=(f[now][j]%p+p)%p;            
41 
42             f[now][0]=(f[now][0]+f[now][j])%p;            
43             f[last][j]=0;
44         }
45         f[last][0]=0,now^=1,last^=1;
46     }
47     printf("%d\n",f[last][0]);
48 }
49 /*
50 3 2 1000
51 3 1 2
52 */

【模擬賽題解錦集】——Hzoi