【题解】2021牛客OI赛前集训营-提高组(第二场)

为出题人点赞

T1.

找规律(良心出题人啊)。

假设 a [ i ] ≠ b [ i ] a[i]\neq b[i] a[i]=b[i] 一共有 t m p tmp tmp 对,一定是 0 / 1 0/1 0/1 组合,那么剩下 0 / 1 0/1 0/1 的数量就是 c n t 0 / c n t 1 − t m p cnt_0/cnt_1-tmp cnt0/cnt1tmp 。又因为 c n t 0 / c n t 1 − t m p cnt_0/cnt_1-tmp cnt0/cnt1tmp 一定是偶数,所以统计 0 / 1 0/1 0/1 出现次数的奇偶性就能求出 t m p tmp tmp

时间复杂度 O ( n + q ) O(n+q) O(n+q)

T2.

组合数 / dp 计数。

我们考虑枚举线段的左右端点,并规定端点必选,这条线段的整点有 N = gcd ⁡ ( i , j ) N=\gcd(i,j) N=gcd(i,j) 个。同时求出 k = ⌈ d / ( i / N ) 2 + ( j / N ) 2 ⌉ k=\lceil d/\sqrt{(i/N)^2+(j/N)^2}\rceil k=d/(i/N)2+(j/N)2

那么方案数为 2 ∗ ( N − 1 N − 1 − ( n − 1 ) ∗ ( k − 1 ) ) 2*\binom{N-1}{N-1-(n-1)*(k-1)} 2(N1(n1)(k1)N1) 。 对横竖的情况特判即可。

#include<bits/stdc++.h> #define db double #define ll long long #define mkp make_pair #define pii pair<int,int> #define inf 0x3f3f3f3f #define fi first #define se second using namespace std; const int mod=1e9+7; const int Maxn=505; inline int read() { int x=0,f=1; char c=getchar(); while(c<'0'||c>'9') { c=getchar(); } while(c>='0'&&c<='9') { x=(x<<1)+(x<<3)+c-'0'; c=getchar(); } return x; } int gcd(int x,int y) { return y==0?x:gcd(y,x%y); } int T; ll C[Maxn][Maxn],res; int n,r,c,d; void add(ll &x,ll y) { x+=y; if(x>=mod) x-=mod; } int main() { // freopen("data.in","r",stdin); for(int i=0;i<=501;i++) { C[i][0]=1; } for(int i=1;i<=501;i++) { for(int j=1;j<=501;j++) { C[i][j]=(C[i-1][j-1]+C[i-1][j])%mod; } } scanf("%d",&T); while(T--) { scanf("%d%d%d%d",&n,&r,&c,&d); if(n==1) { printf("%d\n",(r+1)*(c+1)); continue; } res=0; for(int i=0;i<=r;i++) { for(int j=0;j<=c;j++) { if(i==0&&j==0) continue; int N=gcd(i,j),k=ceil(sqrt(ceil(1.0*d*d/(1.0*(i/N)*(i/N)+1.0*(j/N)*(j/N))))); if((n-1)*k>N) continue; if(i==0||j==0) res=(res+C[N-1-(n-1)*(k-1)][n-2]*(r-i+1)%mod*(c-j+1)%mod)%mod; else res=(res+2*C[N-1-(n-1)*(k-1)][n-2]%mod*(r-i+1)%mod*(c-j+1)%mod)%mod; } } printf("%lld\n",res); } }

T3.

大水题。

可以发现,一个节点 u u u 可以将子树中的两个序列给拼成一个序列,贪心策略为在 u u u 的子树内拼接成尽可能大的序列,再往父节点转移即可。

写一个启发式合并不就完了嘛。(暴力神器)

时间复杂度 O ( n l o g 2 n ) O(nlog^2n) O(nlog2n)

#include<bits/stdc++.h> #define db double #define ll long long #define mkp make_pair #define pii pair<int,int> #define inf 0x3f3f3f3f #define fi first #define se second using namespace std; const int mod=1e9+7; const int Maxn=1e5+5; inline int read() { int x=0,f=1; char c=getchar(); while(c<'0'||c>'9') { c=getchar(); } while(c>='0'&&c<='9') { x=(x<<1)+(x<<3)+c-'0'; c=getchar(); } return x; } int n,id[Maxn],dp[Maxn]; vector<int> g[Maxn]; priority_queue<int> q[Maxn]; void merge(int x,int y) { int tx=id[x],ty=id[y]; if(q[tx].size()>q[ty].size()) { swap(tx,ty); swap(x,y); } while(q[tx].size()) { q[ty].push(q[tx].top()); q[tx].pop(); } id[x]=id[y]; } void dfs(int x,int fa) { for(auto y:g[x]) { if(y==fa) continue; dfs(y,x); merge(x,y); } int du=2; dp[x]=1; while(du&&q[id[x]].size()) { dp[x]+=q[id[x]].top(); q[id[x]].pop(); du--; } q[id[x]].push(dp[x]); } int main() { // freopen("tree2.in","r",stdin); int T=read(); while(T--) { n=read(); for(int i=1;i<=n;i++) { g[i].clear(); while(q[i].size()) q[i].pop(); id[i]=i; } for(int i=1;i<n;i++) { int u=read(),v=read(); g[u].push_back(v); g[v].push_back(u); } dfs(1,0); printf("%d\n",dp[1]); } }

__EOF__

本文作者仰望星空的蚂蚁
本文链接https://www.cnblogs.com/cqbzly/p/17530224.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   仰望星空的蚂蚁  阅读(15)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· DeepSeek 开源周回顾「GitHub 热点速览」
点击右上角即可分享
微信分享提示