Factorial of T1 puzzle
Problem solving ideas
After two answers, it is found that \ (a-b \) is at most 19. After all \ (20! \) is greater than \ (10 ^ {18} \).
For each possible difference, each bisection \ (b+1 \) directly enumerates the product for check.
code
#include<bits/stdc++.h> #define int long long #define ull unsigned long long #define f() cout<<"RP++"<<endl using namespace std; inline int read() { int x=0,f=1;char ch=getchar(); while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();} return x*f; } int T,n,fac[20]; inline int work(int x,int cnt) { __int128 temp=1; for(int i=1;i<=cnt;i++) { temp*=x+i-1; if(temp>n) return 1; } if(temp==n) return 0;return -1; } void solve() { n=read(); if(n==1) return printf("-1\n"),void(); vector<pair<int,int> > ans; for(int cnt=1;cnt<=19&&fac[cnt]<=n;cnt++) { int l=2,r=n-cnt+1,temp=-1; while(l<=r) { int mid=(l+r)>>1,t=work(mid,cnt); if(!t){temp=mid;break;} if(t==-1) l=mid+1; else r=mid-1; } if(~temp) ans.push_back(make_pair(temp+cnt-1,temp-1)); } sort(ans.begin(),ans.end()); printf("%lld\n",(int)ans.size()); for(auto it :ans) printf("%lld %lld\n",it.first,it.second); } #undef int int main() { #define int long long freopen("factorial.in","r",stdin); freopen("factorial.out","w",stdout); T=read(); fac[0]=1; for(int i=1;i<=19;i++) fac[i]=fac[i-1]*i; while(T--) solve(); return 0; }
T2 subset
Problem solving ideas
Assuming that the size of each set is \ (cnt \), if \ (cnt \) is even, you can directly fill in different orders for parity.
Then it can be proved that it is not feasible when \ (n \) is even but \ (cnt \) is odd.
Then, when \ (k,cnt \) are all odd numbers, it is found that if the first three of each set can be successfully arranged, the rest will be treated as even numbers.
For the first column, it's good to arrange directly \ (1,2,3...n \), and for the second column, it's good to fill in the section of \ (\ frac{k+1}{2}+1\sim k \) from large to small, and then fill in the section of \ (1\sim\frac{k+1}{2} \) from large to small.
For the remaining column, it is good to supplement it directly according to the situation of the first two columns.
code
#include<bits/stdc++.h> #define int long long #define ull unsigned long long #define f() cout<<"RP++"<<endl #define count __builtin_popcountll using namespace std; inline int read() { int x=0,f=1;char ch=getchar(); while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();} return x*f; } const int N=1e6+10; int T,n,m,cnt; vector<int> ans[N]; void work1(int bas,int all) { for(int i=1;i<=all;i++) if(i&1) for(int j=1;j<=m;j++) ans[j].push_back(++bas); else for(int j=m;j>=1;j--) ans[j].push_back(++bas); } void work2(int bas=0) { for(int i=1;i<=m;i++) ans[i].push_back(++bas); for(int i=m/2+2;i<=m;i++) ans[i].push_back(++bas); for(int i=1;i<=m/2+1;i++) ans[i].push_back(++bas); for(int i=1;i<=m;i++) ans[i].push_back(3*(3*m+1)/2-ans[i][0]-ans[i][1]); } void solve() { n=read(); m=read(); cnt=n/m; if(m==1){printf("Yes\n");for(int i=1;i<=n;i++)printf("%lld ",i);putchar('\n');return ;} if(n%2==0&&cnt%2) return printf("No\n"),void(); if(cnt%2&&cnt<3) return printf("No\n"),void(); for(int i=1;i<=m;i++) vector<int>().swap(ans[i]); printf("Yes\n"); if(cnt%2==0) work1(0,cnt); else work2(),work1(3*m,cnt-3); for(int i=1;i<=m;i++) { for(auto it:ans[i]) printf("%lld ",it); putchar('\n'); } } #undef int int main() { #define int long long freopen("subset.in","r",stdin); freopen("subset.out","w",stdout); T=read(); while(T--) solve(); return 0; }
T3 concrete powder
Problem solving ideas
The essence of query is to add intervals several times and ask the time when the value at the position of \ (x \) is the earliest \ (\ ge y \).
So we can select the chairman tree, and then the violent dichotomy + chairman tree can reach the complexity of \ (O(qlog^2n) \), and then it will be stuck.
Consider an offline approach. For each insertion operation \ ((l,r,h) \), we record a binary \ ((id,h) \) in two places \ (l,r+1 \).
Then scan the sequence of line scan \ (1\sim n \) and process the answer with a tree array or line segment tree based on the operation label to maintain the height.
In this way, we have the relative time relationship and corresponding height of all influential operations for each subscript.
Find one answer in two at a time. The subscript \ (mid \) uses the tree array to find the height reached by the \ (mid \) operation and previous operations. check.
This is the binary tree array. Because the constant is excellent, it can be stuck. The binary of line segment tree or tree array is also a similar idea.
code
Super constant chairman tree
#include<bits/stdc++.h> #define ll long long #define ls tre[x].l #define rs tre[x].r using namespace std; inline ll read() { ll x=0,f=1;char ch=getchar(); while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();} return x*f; } const int N=1e6+10; int n,q,all,rt,root[N],id[N]; ll cnt; struct Segment_Tree { struct Node{int l,r;ll dat;}tre[N*35]; inline int insert(register int pre,register int l,register int r,register int L,register int R,register int val) { register int x=++all,mid=(l+r)>>1; tre[x]=tre[pre]; if(L<=l&&r<=R) return tre[x].dat+=val,x; if(L<=mid) ls=insert(tre[pre].l,l,mid,L,R,val); if(R>mid) rs=insert(tre[pre].r,mid+1,r,L,R,val); return x; } inline void query(register int x,register int l,register int r,register int pos) { if(!x||l==r) return cnt+=tre[x].dat,void(); register int mid=(l+r)>>1; if(pos<=mid) return cnt+=tre[x].dat,query(ls,l,mid,pos),void(); return cnt+=tre[x].dat,query(rs,mid+1,r,pos),void(); } }T; int main() { freopen("concrete.in","r",stdin); freopen("concrete.out","w",stdout); n=read(); q=read(); for(register int i=1,opt,x,z;i<=q;i++) { ll y; opt=read(); x=read(); y=read(); cnt=0; if(opt==1){z=read();id[++rt]=i;root[rt]=T.insert(root[rt-1],1,n,x,y,z);continue;} T.query(root[rt],1,n,x); if(cnt<y){printf("0\n");continue;} register int l=0,r=rt,ans=0; while(l<=r) { register int mid=(l+r)>>1; cnt=0; T.query(root[mid],1,n,x); if(cnt>=y) ans=id[mid],r=mid-1; else l=mid+1; } printf("%d\n",ans); } return 0; }
Binary tree array
#include<bits/stdc++.h> #define int long long #define ull unsigned long long #define f() cout<<"RP++"<<endl using namespace std; inline int read() { int x=0,f=1;char ch=getchar(); while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();} return x*f; } const int N=1e6+10; int n,q,cnt,ans[N]; vector< pair<int,int> > v[N],ask[N]; struct BIT { int lim,tre[N]; #define lowbit(x) (x&(-x)) inline void insert(int x,int val){for(int i=x;i<=lim;i+=lowbit(i))tre[i]+=val;} inline int query(int x){int sum=0;for(int i=x;i;i-=lowbit(i))sum+=tre[i];return sum;} }T; #undef int int main() { #define int long long freopen("concrete.in","r",stdin); freopen("concrete.out","w",stdout); n=read(); q=read(); T.lim=q; memset(ans,-1,sizeof(ans)); for(int i=1,opt,x,y,z;i<=q;i++) { opt=read(); x=read(); y=read(); if(opt==2){ask[x].push_back(make_pair(i,y));continue;} z=read(); v[x].push_back(make_pair(i,z)); v[y+1].push_back(make_pair(i,-z)); } for(int i=1;i<=n;i++) { for(auto it:v[i]) T.insert(it.first,it.second); for(auto it:ask[i]) { int l=1,r=it.first; ans[it.first]=0; while(l<=r) { int mid=(l+r)>>1,temp=T.query(mid); if(temp>=it.second) ans[it.first]=mid,r=mid-1; else l=mid+1; } } } for(int i=1;i<=q;i++) if(~ans[i]) printf("%lld\n",ans[i]); return 0; }
T4 drainage system
Problem solving ideas
Consider the effect of edge \ ((x,y) \) blockage.
In fact, the contribution to other outlets of \ (x \) increases, while the contribution to \ (y \) decreases.
It means that we can add the contribution to the \ (x \) point and then subtract it from the \ (y \) point.
The specific realization is to ignore all aging conditions, calculate that there should be sewage at each point, and then calculate the initial expected sewage at each point on the basis of sequence.
Just run again at last.
code
#include<bits/stdc++.h> #define int long long #define ull unsigned long long #define f() cout<<"RP++"<<endl using namespace std; inline int read() { int x=0,f=1;char ch=getchar(); while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();} return x*f; } const int N=2e5+10,M=5e5+10,mod=998244353; int n,m,base,sta[N],r,ed,cnt[N],du[N],f[N],g[N]; int tot,head[N],ver[M],nxt[M],edge[M],fro[M]; void add(int &x,int y){x+=y;if(x>=mod)x-=mod;} void add_edge(int x,int y,int val) { ver[++tot]=y; edge[tot]=val; fro[tot]=x; du[y]++; cnt[x]++; nxt[tot]=head[x]; head[x]=tot; } int power(int x,int y,int p=mod) { int temp=1; for(;y;y>>=1,x=x*x%p) if(y&1) temp=temp*x%p; return temp; } #undef int int main() { #define int long long freopen("water.in","r",stdin); freopen("water.out","w",stdout); n=read(); m=read(); r=read(); ed=read(); for(int i=1,x,y,val;i<=ed;i++) { x=read(); y=read(); val=read(); add_edge(x,y,val); add(base,val); } int top=0,pos=0; base=power(base,mod-2); for(int i=1;i<=m;i++) sta[++top]=i; while(top<n) { int x=sta[++pos]; for(int i=head[x];i;i=nxt[i]) { int to=ver[i]; du[to]--; if(!du[to]) sta[++top]=to; } } for(int i=1;i<=m;i++) f[i]=1; for(int i=1;i<=n;i++) { int x=sta[i],temp=power(cnt[x],mod-2)*f[x]%mod; for(int j=head[x];j;j=nxt[j]) add(f[ver[j]],temp); } for(int i=1;i<=n;i++) { if(!cnt[i]) continue; int temp=f[i]*power(cnt[i]-1,mod-2)%mod; for(int j=head[i];j;j=nxt[j]) { add(g[i],temp*edge[j]%mod*base%mod); add(g[ver[j]],(mod-temp%mod)*edge[j]%mod*base%mod); } } for(int i=1;i<=m;i++) add(g[i],1); for(int i=1;i<=n;i++) { int x=sta[i],temp=power(cnt[x],mod-2)*g[x]%mod; for(int j=head[x];j;j=nxt[j]) add(g[ver[j]],temp); } for(int i=n-r+1;i<=n;i++) printf("%lld ",g[i]); return 0; }