T1 异或 T2 赌神 T3 路径 T4 树
T1 异或

比较稳的切掉

观察数据范围,无法线性筛啥的,根号复杂度也会死,于是只能考虑$log$级

然后打表

发现当$n$为$2^i$时的答案是一个可递归数列:

$1,3,7,15,31,63,127...$

这样的话直接把$n$进行二进制拆分,然后累加$2^i$的答案就可以出来最终答案

Noip模拟52 2021.9.13_i++Noip模拟52 2021.9.13_i++_02
 1 #include<bits/stdc++.h>
 2 #define int long long
 3 using namespace std;
 4 namespace AE86{
 5     inline int read(){
 6         int x=0,f=1;char ch=getchar();
 7         while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
 8         while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}return x*f;
 9     }inline void write(int x,char opt='\n'){
10         char ch[20];int len=0;if(x<0)x=~x+1,putchar('-');
11         do{ch[len++]=x%10+(1<<5)+(1<<4);x/=10;}while(x);
12         for(register int i=len-1;i>=0;--i)putchar(ch[i]);putchar(opt);}
13 }using namespace AE86;
14 
15 const int NN=1e6+5,inf=0x3fffffff;
16 int n,er[65],cnt,pw,i,ans;
17 
18 inline int getnum(int x){
19     if(x==1) return 1;
20     return getnum(x/2)*2+1;
21 }
22 
23 namespace WSN{
24     inline short main(){
25         n=read();
26         while(n>0){
27             pw=1,i=0;while(pw<=n) pw<<=1,++i;
28             --i; pw>>=1; n-=pw; er[++cnt]=pw;
29         }
30         for(i=1;i<=cnt;i++) ans+=getnum(er[i]);
31         write(ans);
32         return 0;
33     }
34 }
35 signed main(){return WSN::main();}
View Code

 

T2 赌怪

一道神仙$dp$题成功被乱搞为贪心。

按照题意模拟过程,每次找到最多的颜色种类然后按比例累乘答案即可

Noip模拟52 2021.9.13_i++Noip模拟52 2021.9.13_i++_02
 1 #include<bits/stdc++.h>
 2 #define int long long
 3 using namespace std;
 4 namespace AE86{
 5     inline int read(){
 6         int x=0,f=1;char ch=getchar();
 7         while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
 8         while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}return x*f;
 9     }inline void write(int x,char opt='\n'){
10         char ch[20];int len=0;if(x<0)x=~x+1,putchar('-');
11         do{ch[len++]=x%10+(1<<5)+(1<<4);x/=10;}while(x);
12         for(register int i=len-1;i>=0;--i)putchar(ch[i]);putchar(opt);}
13 }using namespace AE86;
14 
15 const int NN=1e6+5,inf=0x3fffffff,mod=998244353;
16 inline int qmo(int a){
17     int ans=1,c=mod,b=c-2; a%=c;
18     while(b){
19         if(b&1) ans=ans*a%c;
20         b>>=1; a=a*a%c;
21     } return ans;
22 }
23 
24 int n,a[NN],tot,ans=1,x;
25 priority_queue<int> q;
26 
27 namespace WSN{
28     inline short main(){
29         n=read();
30         for(int i=1,a;i<=n;i++){
31             a=read(); tot+=a;
32             q.push(a);
33         }
34         while(!q.empty() && q.top() && tot){
35             x=q.top(); q.pop();
36             (ans*=n*x*qmo(tot)%mod)%=mod; --tot;
37             q.push(x-1);
38         }
39         write(ans);
40         return 0;
41     }
42 }
43 signed main(){return WSN::main();}
View Code

考场上还是要敢猜测答案,要不然会错失好机会

 

高能预警:T3T4暴力分数极高,无法想像暴力打满有200分

T3 路径

不少人点分治$n^2logn$能切(只因为我考场上打的点分治无法契合测试点(究级离谱)???)???

还有不少人使用$FFT$能切,(只有战神切的用正解:“您知道这是$OJ$上的原题吗?”)

确实是斯特林数的原题,也确实只有战神切掉了那道原题。。。。。

$x^i=\sum _{j=0}^{i}\begin{Bmatrix}k\\i \end{Bmatrix}*x^{\underline i}$

斯特林数小于100可以预处理。剩下的就需要求出$\sum_{u=0}^{k}\sum_{x=1}^{n-1}\sum_{y=x+1}^{n}dist(x,y)^{\underline u}$

考虑$dp$,设$f[i][j]=\sum_{u \in sub(i)}dis(fa[i],u)^{\underline j}$这个东西可以$dfs$预处理:

定义一个转移数组$g[i][j]=\sum_{son}f[son][j]=\sum_{son}(dis(i,u)-1)^{\underline j}$

发现用这个转移到$f[i][j]$可以用下降幂公式:$(x+1)^{\underline i}=i*x^{\underline {i-1}}+x^{\underline i}$

那么$f[i][j]=g[i][j-1]*j+g[i][j]$

然后考虑换根$dp$,

Noip模拟52 2021.9.13_c++_05

 

 太丑,不过能看

从$fa$转移到$i$,考虑几件事情

1.现在的$g[fa][j]-f[i][j]$,算出$fa$剩下子树的贡献和

2.这个贡献算出新的$f[fa][j]$用下降幂公式,表示$fa$成为了$i$的子树后,对$i$作出的贡献

3.累加新的根的答案,新的$g[i][j]$为累加上那个$fa$的转移值

然后答案$ans_i=\sum_{u}g[u][i]$

最后答案=$\sum_{i}S[k][i]*ans[i]$

Noip模拟52 2021.9.13_i++Noip模拟52 2021.9.13_i++_02
 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int NN=1e6+5,inf=0x3fffffff,mod=998244353,v2=499122177;
 4 namespace AE86{
 5     inline int read(){
 6         int x=0,f=1;char ch=getchar();
 7         while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
 8         while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}return x*f;
 9     }inline void write(int x,char opt='\n'){
10         char ch[20];int len=0;if(x<0)x=~x+1,putchar('-');
11         do{ch[len++]=x%10+(1<<5)+(1<<4);x/=10;}while(x);
12         for(register int i=len-1;i>=0;--i)putchar(ch[i]);putchar(opt);}
13     inline int max(int a,int b){return a>b?a:b;}
14     inline int min(int a,int b){return a<b?a:b;}
15     inline int mo(int x){return x>=mod?x-mod:x;}
16 }using namespace AE86;
17 
18 struct SNOW{int to,next;}e[NN<<1]; int head[NN],rp;
19 inline void add(int x,int y){
20     e[++rp]=(SNOW){y,head[x]};head[x]=rp;
21     e[++rp]=(SNOW){x,head[y]};head[y]=rp;
22 }
23 
24 int n,k,S[105][105],f[NN][101],g[NN][101],ans[105],tmp[105],answer;
25 
26 inline void dfs(int fa,int x){
27     int maxn=0;
28     for(int i=head[x];i;i=e[i].next) if(fa!=e[i].to){
29         dfs(x,e[i].to);
30         for(int j=0;j<=k;j++){
31             if(!f[e[i].to][j]) break; maxn=max(maxn,j);
32             g[x][j]=mo(g[x][j]+f[e[i].to][j]);
33         }
34     }
35     ++g[x][0]; f[x][0]=g[x][0];
36     for(int i=min(k,maxn+1);i;--i)
37         f[x][i]=mo(1ll*i*g[x][i-1]%mod+g[x][i]);
38 }
39 
40 inline void get(int fa,int x){
41     int maxn=0;
42     for(int i=0;i<=k;i++){
43         if(!g[x][i]) break;maxn=i;
44         ans[i]=mo(ans[i]+g[x][i]);
45     } maxn=min(k,maxn+1);
46     for(int i=head[x];i;i=e[i].next) if(fa!=e[i].to){
47         for(int j=0;j<=maxn;j++) tmp[j]=mo(g[x][j]-f[e[i].to][j]+mod);
48         for(int j=maxn;j;j--) tmp[j]=mo(tmp[j]+1ll*tmp[j-1]*j%mod);
49         for(int j=0;j<=maxn;j++) g[e[i].to][j]=mo(tmp[j]+g[e[i].to][j]);
50         get(x,e[i].to);
51     }
52 }
53 
54 namespace WSN{
55     inline short main(){
56         // freopen("in.in","r",stdin);
57         // freopen("std.out","w",stdout);
58         n=read(); k=read(); S[0][0]=1;
59         for(int i=1;i<=k;i++) for(int j=1;j<=i;j++)
60             S[i][j]=mo(S[i-1][j-1]+1ll*S[i-1][j]*j%mod);
61         for(int i=1,u,v;i<n;i++) u=read(),v=read(),add(u,v);
62         dfs(0,1); get(0,1); 
63         for(int i=0;i<=k;i++) answer=mo(answer+1ll*S[k][i]*ans[i]%mod);
64         answer=1ll*answer*v2%mod;
65         write(answer);
66         return 0;
67     }
68 }
69 signed main(){return WSN::main();}
View Code

 

T4 树

考场上都用暴力水过了,可是我没太管这道题,可恶。。。

Noip模拟52 2021.9.13_i++Noip模拟52 2021.9.13_i++_02
 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 namespace AE86{
 4     inline int read(){
 5         int x=0,f=1;char ch=getchar();
 6         while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
 7         while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}return x*f;
 8     }inline void write(int x,char opt='\n'){
 9         char ch[20];int len=0;if(x<0)x=~x+1,putchar('-');
10         do{ch[len++]=x%10+(1<<5)+(1<<4);x/=10;}while(x);
11         for(register int i=len-1;i>=0;--i)putchar(ch[i]);putchar(opt);}
12 }using namespace AE86;
13 
14 const int NN=3e5+1;
15 struct SNOW{int to,next;}e[NN<<1]; int head[NN],rp;
16 inline void add(int x,int y){
17     e[++rp]=(SNOW){y,head[x]};head[x]=rp;
18     e[++rp]=(SNOW){x,head[y]};head[y]=rp;
19 }
20 int n,q,rt[NN],dfn[NN],cnt,dep[NN],siz[NN],ans,maxdep;
21 inline void dfs(int f,int x){
22     dfn[x]=++cnt; dep[x]=dep[f]+1; siz[x]=1; maxdep=max(maxdep,dep[x]);
23     for(int i=head[x];i;i=e[i].next) if(f!=e[i].to)
24         dfs(x,e[i].to),siz[x]+=siz[e[i].to];
25 }
26 
27 struct SNOWtree{
28     int ls[NN*40],rs[NN*40],seg,sum[NN*40];
29     inline void insert(int &x,int l,int r,int L,int R,int val){
30         if(!x) x=++seg;
31         if(L<=l&&r<=R){sum[x]+=val;return;}
32         int mid=(l+r)>>1;
33         if(l<=mid) insert(ls[x],l,mid,L,R,val);
34         if(r>mid) insert(rs[x],mid+1,r,L,R,val);
35     }
36     inline int query(int x,int l,int r,int pos){
37         ans+=sum[x]; if(l==r) return ans;
38         int mid=(l+r)>>1;
39         if(pos<=mid) return query(ls[x],l,mid,pos);
40         else return query(rs[x],mid+1,r,pos);
41     }
42 }tr;
43 
44 namespace WSN{
45     inline short main(){
46         n=read(); q=read();
47         for(int i=1,u,v;i<n;i++){
48             u=read(),v=read();
49             add(u,v);
50         } dfs(0,1);
51         int opt,v,x,z,y,res;
52         while(q--){
53             opt=read(),v=read();
54             if(opt==1){
55                 x=read(),y=read(),z=read(); res=y+dep[v];
56                 for(res=y+dep[v];res<=maxdep;res+=x)
57                     tr.insert(rt[res],1,n,dfn[v],dfn[v]+siz[v]-1,z);
58             }
59             if(opt==2){ans=0;write(tr.query(rt[dep[v]],1,n,dfn[v]));}
60         }
61         return 0;
62     }
63 }
64 signed main(){return WSN::main();}
可过但被卡的暴力

然而暴力被卡掉了,在晚上,所以姑姑沽