solve 6/11
补题:
Code:zz
Thinking:zz kk
把每个节点的深度都处理出来,同一深度的点的冲突度为 (x-1),x为同层次点数减一。
然后冲突度不断下传(冲突度为3,则最多下传3层)
最后答案就是最后一层的深度加上冲突度。
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
#include<bits/stdc++.h> #define CLR(a,b) memset(a,b,sizeof(a)) using namespace std; typedef long long ll; const int maxn=100010; int n,m; int a[maxn]; bool vis[maxn]; ll ans[maxn],No[maxn]; struct egde{ int to,Next; }e[maxn<<1]; struct node{ int u; ll time; }; int head[maxn],tot; void init(){ CLR(head,-1),tot=0; CLR(vis,0); CLR(ans,0); CLR(No,0); } void addv(int u,int v){ e[++tot].to=v; e[tot].Next=head[u]; head[u]=tot; } void bfs(){ queue<node >q; q.push({1,0}); vis[1] = true; ans[1] = 1; if(a[1]) { No[1]++; } while(!q.empty()) { node s=q.front(); q.pop(); int u=s.u; ll time=s.time; for(int i=head[u];i!=-1;i=e[i].Next) { int v=e[i].to; if(!vis[v]) { vis[v] = true; q.push({v,time + 1}); ans[v] = time + 1 + 1; if(a[v]) { No[time + 1 + 1]++; } } } } } int main(){ while(cin>>n) { for(int i=1;i<=n;i++) { scanf("%d",&a[i]); } init(); for(int i=1;i<n;i++) { int u,v; scanf("%d%d",&u,&v); addv(u,v),addv(v,u); } bfs(); ll aans = 0,mm = 0; for(int i = 1;i <= n;i++) { if(a[i]) { mm = max(mm,ans[i]); } } for(int i = 1;i <= n;i++) { if(mm == i) { break; } No[i + 1] += max((ll)0,No[i] - 1); } printf("%lld\n",No[mm] - 1 + mm - 1); } }
Code:pai爷 zz kk
Thinking:pai爷 zz kk
根据式子观察得,这个式子就是斐波那契数列丢掉自己二进制的低位1的前缀和,也就是 fib n - lowbit(fib n),所以暴力打表把减掉的这部分打出来,找规律,然后矩阵快速幂求斐波那契数列前n项和,减一减。
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
#include<cstdio> #include<cmath> #include<cstring> #include<cstdlib> #include<algorithm> #include<iostream> #include<map> using namespace std; typedef long long ll; const int p=998244353; const int mod = 998244353; ll f[1010],sum[1010],r; int t; void mul(ll f[3], ll a[3][3]) { ll c[3]; memset(c, 0, sizeof(c)); for (int j = 0; j < 3; j++) for (int k = 0; k < 3; k++) c[j] = (c[j] + (long long)f[k] * a[k][j]%mod) % mod; memcpy(f, c, sizeof(c)); } void mulself(ll a[3][3]) { ll c[3][3]; memset(c, 0, sizeof(c)); for (int i = 0; i < 3; i++) for (int j = 0; j < 3; j++) for (int k = 0; k < 3; k++) c[i][j] = (c[i][j] + (long long)a[i][k] * a[k][j]%mod) % mod; memcpy(a, c, sizeof(c)); } ll quickm(ll n){//求第n项和 ll f[3] = { 1,1,1 }; ll tep=n-1; ll a[3][3] = { {1,1,1},{1,0,0},{0,0,1} }; for (; tep; tep >>= 1) { if (tep & 1) mul(f, a); mulself(a); } return f[2]; } ll solve(ll x,int w) { if(x==0) return 0; if(x==1) return 1; if(x==2) return 2; if(x==3) return 4; if(x==4) return 5; if(x==5) return 6; if(x==6) return 14; for(int i=w;i>=1;i--) if(x>=1ll*6*f[i]) { return (sum[i]+solve(x-6*f[i],i-1))%p; } } int main() { f[1]=1;sum[1]=14; for(int i=2;i<=61;i++) { f[i]=f[i-1]*2; sum[i]=(sum[i-1]*2%p+f[i]*4%p)%p; } scanf("%d",&t); while(t--) { scanf("%lld",&r); ll ans=solve(r,61); //printf("%lld\n",ans); printf("%lld\n",(quickm(r)-ans+p)%p); } }
待补题 初中数学
Code:kk
Thinking:kk
先把每个b[ i ]的余数求出来,余数等于i的说明没有冲突,不等于i的,假设偏移量为px,说明他的前px项都在他前面,所以就得到拓扑序,由于要字典序最小,所以用优先队列求拓扑序列。
div2暴力建边即可,div1要线段树优化建边?待学习。
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
#include<bits/stdc++.h> #include<unordered_map> #define CLR(a,b) memset(a,b,sizeof(a)) using namespace std; typedef long long ll; const int maxn=1010; int n; ll a[maxn],b[maxn],m[maxn]; int dg[maxn]; struct egde{ int to,Next; }e[maxn*maxn]; int head[maxn],tot; void init(){ CLR(head,-1),tot=0; } void addv(int u,int v){ e[++tot].to=v; e[tot].Next=head[u]; head[u]=tot; } struct node{ int pos; ll val; friend bool operator <(const node &a,const node &b){ return a.val>b.val; } }; priority_queue<node >q; void Top(){ int top=0; while(!q.empty()){ node s=q.top(); q.pop(); a[++top]=s.val; for(int i=head[s.pos];i!=-1;i=e[i].Next) { int pos=e[i].to; dg[pos]--; if(dg[pos]==0) { q.push({pos,b[pos]}); } } } } int main(){ while(cin>>n) { init(); for(int i=0;i<n;i++) { scanf("%lld",&b[i]); m[i]=b[i]%n; } for(int i=0;i<n;i++) { if(m[i]==i) { q.push({i,b[i]}); }else{ int px=(i-m[i]+n)%n; while(px>0) { addv((i-px+n)%n,i); dg[i]++; px--; } } } Top(); for(int i=1;i<=n;i++) { printf("%lld%c",a[i],(i<n)?' ':'\n'); } } }
Code:pai爷
Thinking:pai爷
0(n*n)枚举每个数对有贡献的答案为不相同的最高位。
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
#include<iostream> #include<cstring> #include<cmath> #include<algorithm> #include<cstdio> #include<cstdlib> using namespace std; const int p=998244353; int n,m,x,f[1010][50]; int sum,ans=0,chu,yu,a,b; int main() { // freopen("1.txt","r",stdin); // freopen("1.out","w",stdout); scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) { scanf("%d",&x); int l=0; while(x>0) { f[i][++l]=x%2; x/=2; } f[i][0]=l; } for(int i=1;i<=n;i++) for(int j=i+1;j<=n;j++) { int k; for(k=max(f[j][0],f[i][0]);k>=1;k--) if(f[i][k]!=f[j][k]) break; chu=m/(1<<(k-1));yu=m%(1<<(k-1)); a=(chu-chu/2)*(1<<(k-1))-1;b=chu/2*(1<<(k-1)); sum=yu+1; //printf("chu=%d yu=%d a=%d b=%d sum=%d k=%d\n",chu,yu,a,b,sum,k); if(chu%2==0) a+=sum,b=m-a; else b+=sum,a=m-b; if(f[i][k]==0) ans=(ans+b)%p; else ans=(ans+a)%p; ans=(ans+p)%p; //printf("%d\n",ans); } printf("%d\n",ans); }
Code:zz
Thinking:zz
暴力枚举每个人是机器人的情况,再dfs查找出所有的机器人,选取机器人最少的情况。
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
//#pragma comment(linker, "/STACK:102400000,102400000") #include<iostream> #include<stdio.h> #include<stdlib.h> #include<string.h> #include<string> #include<math.h> #include<cmath> #include<time.h> #include<map> #include<set> #include<vector> #include<queue> #include<algorithm> #include<numeric> #include<stack> #include<bitset> #include<unordered_map> const int maxn = 0x3f3f3f3f; const double EI = 2.71828182845904523536028747135266249775724709369995957496696762772407663035354594571382178525166427; const double PI = 3.141592653589793238462643383279; using namespace std; struct s { int k; int c[110]; }z[110]; vector<int>ve[110]; int vis[110]; unordered_map<int,int>mp[110]; inline void dfs(int pos) { int si,i; si = ve[pos].size(); for(i = 0;i < si;i++) { if(!vis[ve[pos][i]]) { vis[ve[pos][i]] = 1; dfs(ve[pos][i]); } } } int main(void) { //ios::sync_with_stdio(false); int n,m,i,j,ans,mi,l; while(~scanf("%d %d",&n,&m)) { for(i = 0;i <= n;i++) { ve[i].clear(); mp[i].clear(); } for(i = 0;i < m;i++) { scanf("%d",&z[i].k); for(j = 0;j < z[i].k;j++) { scanf("%d",&z[i].c[j]); } } for(i = 0;i < m;i++) { for(j = z[i].k - 1;j >= 0;j--) { for(l = j - 1;l >= 0;l--) { if(!mp[z[i].c[j]][z[i].c[l]]) { mp[z[i].c[j]][z[i].c[l]] = 1; ve[z[i].c[j]].push_back(z[i].c[l]); } } } } ans = 100000; for(i = 1;i <= n;i++) { memset(vis,0,sizeof(vis)); vis[i] = 1; dfs(i); mi = 0; for(j = 1;j <= n;j++) { if(vis[j]) { mi++; } } ans = min(ans,mi); } printf("%d\n",ans); } return 0; }
求补图,然后dp?待补
Code:pai爷
Thinking:pai爷
暴力打表?待补
赛后总结
kk:今天是演员的一天,演队友演自己,开局A题就想错了思路,然后一直想错,两小时才把A题这水题做了,然后E题基本读完题意,稍微写写就得到正解了,结果建边数组少开了,re一发,给队友写个矩阵快速幂的板子,没注意数据范围,long long写成了int,tle一发。影帝影帝,以后演技要好一些,要注意细节。
pai爷:模数复制粘贴错误找了一个小时的bug而且还wa了三发。找规律速度不够快。
zz:这场比赛演技越来越好了,水题想了好多假算法,而且wa以后才发现。找规律的题贡献了一个表。