B.Mister B and PR Shifts
分类讨论一下就好了。
#include <bits/stdc++.h> #define for1(a,b,i) for(int i=a;i<=b;++i) #define FOR2(a,b,i) for(int i=a;i>=b;--i) using namespace std; typedef long long ll; #define M 1000005 int n; int a[M]; ll sum[M],index_[M]; inline void add_(int l,int r,int x,int opt) { sum[l]+=x,sum[r+1]-=x; index_[l]+=opt,index_[r+1]-=opt; } int main () { scanf("%d",&n); for1(1,n,i) scanf("%d",a+i); for1(1,n,i) { if(a[i]>i) { int l=0,r=a[i]-i; if(l<=r) add_(l,r,a[i]-i,-1); l=r+1,r=n-i; if(l<=r) add_(l,r,i-a[i],1); l=r+1,r=n-1; if(l<=r) add_(l,r,a[i]-i+n,-1); } else { int l=0,r=n-i; if(l<=r) add_(l,r,i-a[i],1); l=r+1,r=min(a[i]+n-i,n-1); if(l<=r) add_(l,r,a[i]-i+n,-1); l=r+1,r=n-1; if(l<=r) add_(l,r,i-n-a[i],1); } } for1(1,n-1,i) { index_[i]+=index_[i-1]; sum[i]+=sum[i-1]; } for1(1,n-1,i) sum[i]+=i*index_[i]; int ans=0; for1(1,n-1,i) if(sum[i]<sum[ans]) ans=i; printf("%lld %d ",sum[ans],ans); }
C.Mister B and Beacons on Field
容易推出答案就是$sum_{d|2S}[d<=n]+sum_{i=1}^{m}2S|gcd(i,n)$
$2S$的因子个数很好搞,直接分解完枚举所有因子就行了,$1e5$级别的。
考虑怎么求第二个式子。
考虑对于$p$,若$cnt_n[p]>cnt_2S[p]$,才有可能使得不满足条件。
直接把所有的$p$都找出来容斥一发就行了。
感觉自己的代码真的丑,看了一发别人的代码,还是$STL$好用啊,学会正确使用$STL$。
#include <bits/stdc++.h> #define for1(a,b,i) for(int i=a;i<=b;++i) #define FOR2(a,b,i) for(int i=a;i>=b;--i) using namespace std; typedef long long ll; #define M 1100005 ll n,m,S,ans; int a[3],b[3],s[3]; vector <ll> cc; map <int,int> sp,np; inline void trans_(map<int,int>::iterator x,ll sum) { if(sum>n) return; if(x==sp.end()) return ++ans,void(); ll now=1; auto it=x; it++; for1(0,x->second,i) { trans_(it,sum*now); now*=x->first; } } int main () { //freopen("a.in","r",stdin); int Test_; scanf("%d",&Test_); while (Test_--) { ans=0; n=m=1,S=2; sp.clear(),np.clear(),cc.clear(); scanf("%d%d%d%d%d%d%d%d%d",a,a+1,a+2,b,b+1,b+2,s,s+1,s+2); n=n*a[0]*a[1]*a[2],m=m*b[0]*b[1]*b[2],S=S*s[0]*s[1]*s[2]; sp[2]=1; for1(2,1000,i) { for1(0,2,j) while (a[j]%i==0) a[j]/=i,++np[i]; for1(0,2,j) while (s[j]%i==0) s[j]/=i,++sp[i]; } for1(0,2,i) if(a[i]>1) ++np[a[i]]; for1(0,2,i) if(s[i]>1) ++sp[s[i]]; trans_(sp.begin(),1); for(auto i=np.begin();i!=np.end();i++) if(sp[i->first]<i->second) { ll x=1; FOR2(sp[i->first]+1,1,j) x=x*i->first; cc.push_back(x); } int size=cc.size(); FOR2((1<<size)-1,0,i) { ll x=m; int opt=1; for1(1,size,j) if(i>>j-1&1) opt*=-1,x/=cc[j-1]; ans+=opt*x; } printf("%lld ",ans); } }
D.Mister B and Astronomers
首先显然可以分成$T/gcd(T,sum)$类。
对于不同类别之间不相互影响。
对于同类的我们可以算出$g[i]$代表$(sum[1]+g[i]*T) mod T == sum[i]$。
又因为每个人可以得到的是一个前缀(显然可以证明)。
然后直接用个$set$查个后继就行了。
#include <bits/stdc++.h> #define for1(a,b,i) for(int i=a;i<=b;++i) #define FOR2(a,b,i) for(int i=a;i>=b;--i) using namespace std; typedef long long ll; inline int read () { int f=1,sum=0; char x=getchar(); for(;(x<'0'||x>'9');x=getchar()) if(x=='-') f=-1; for(;x>='0'&&x<='9';x=getchar()) sum=sum*10+x-'0'; return f*sum; } #define M 200005 int T,n; int GCD,x_,y_,num; int a[M],f[M],g[M],id[M],sum[M],ans[M]; multiset <int> cc; map <int,bool> vis; inline bool comp(int x,int y) {return f[x]==f[y]?x<y:f[x]<f[y];} inline int ex_gcd(int a,int b,int &x,int &y) { if(!b) return x=1,y=0,a; int d=ex_gcd(b,a%b,x,y); int t=x; x=y; y=t-(a/b)*y; return d; } inline int calc_(int x) { if(vis.count(g[x])) return 0; if(!cc.size()) return num; int c=(g[x]+1)%num; auto it=cc.lower_bound(c); if(it==cc.end()) it=cc.begin(); //cout<<x<<" "<<*it<<" "<<g[x]<<endl; return *it-g[x]+(g[x]>=*it)*num; } int main () { //freopen("a.in","r",stdin); T=read(),n=read(); for1(1,n,i) { a[i]=read(); sum[0]=(sum[0]+a[i])%T; if(i>1) sum[i]=(sum[i-1]+a[i])%T; } GCD=ex_gcd(sum[0],T,x_,y_); num=T/GCD; if(x_<0) x_+=((-x_-1)/num+1)*num; if(x_>0) x_-=(x_-1)/num*num; for1(1,n,i) { f[i]=sum[i]; f[i]=min(f[i],(sum[i]+((T-sum[i]-1)/GCD+1)*GCD)%T); } for1(1,n,i) id[i]=i; sort(id+1,id+n+1,comp); for(int l=1,r;l<=n;l=r+1) { r=l; while (r<n&&f[id[l]]==f[id[r+1]]) ++r; int cnt=r-l+1; for1(1,cnt,i) { int x=id[i+l-1]; int c=sum[x]-sum[id[l]]; if(c>=0) g[i]=1ll*c/GCD*x_%num; else g[i]=1ll*(c+T)/GCD*x_%num; cc.insert(g[i]); } for1(1,cnt,i) { cc.erase(cc.lower_bound(g[i])); ans[id[i+l-1]]=calc_(i); cc.insert(g[i]); vis[g[i]]=1; } cc.clear(),vis.clear(); } for1(1,n,i) printf("%d ",ans[i]); puts(""); }
E.Mister B and Flight to the moon
按照$mod4$分类讨论就行了。
#include <bits/stdc++.h> #define for1(a,b,i) for(int i=a;i<=b;++i) #define FOR2(a,b,i) for(int i=a;i>=b;--i) using namespace std; typedef long long ll; #define M 305 int n; int e_size; struct node { int size,a,b,c,d; }e[M*M]; int main () { //freopen("a.in","r",stdin); scanf("%d",&n); if(n<=2) return puts("-1"),0; if(n==3) { puts("2"); puts("3 1 2 3"); puts("3 1 2 3"); return 0; } if(n%4==0) { for(int i=1;i<=n;i+=4) { int a=i,b=i+1,c=i+2,d=i+3; e[++e_size]=(node){3,a,b,c}; e[++e_size]=(node){3,a,c,d}; e[++e_size]=(node){3,c,d,b}; e[++e_size]=(node){3,d,b,a}; } for(int i=1;i<=n;i+=2) { int x=i,y=i+1; for(int j=i+2+(i%4==1)*2;j<=n;j+=2) { int a=j,b=j+1; e[++e_size]=(node){4,x,a,y,b}; e[++e_size]=(node){4,x,a,y,b}; } } } else if(n%4==1) { --n; for(int i=1;i<=n;i+=2) { int x=i,y=i+1; for(int j=i+2;j<=n;j+=2) { int a=j,b=j+1; e[++e_size]=(node){4,x,a,y,b}; e[++e_size]=(node){4,x,a,y,b}; } e[++e_size]=(node){3,x,y,n+1}; e[++e_size]=(node){3,x,y,n+1}; } } else if(n%4==2) { n-=2; for(int i=1;i<=n;i+=2) { int x=i,y=i+1; for(int j=i+2;j<=n;j+=2) { int a=j,b=j+1; e[++e_size]=(node){4,x,a,y,b}; e[++e_size]=(node){4,x,a,y,b}; } if(i==1) { e[++e_size]=(node){3,x,n+1,n+2}; e[++e_size]=(node){3,n+1,n+2,y}; e[++e_size]=(node){3,n+2,y,x}; e[++e_size]=(node){3,y,x,n+1}; } else { e[++e_size]=(node){3,x,y,n+2}; e[++e_size]=(node){3,y,x,n+1}; e[++e_size]=(node){4,x,n+1,y,n+2}; } } } else { n-=3; e[++e_size]=(node){3,n+1,n+2,n+3}; e[++e_size]=(node){3,n+1,n+2,n+3}; for(int i=1;i<=n;i+=2) { int x=i,y=i+1; for(int j=i+2;j<=n;j+=2) { int a=j,b=j+1; e[++e_size]=(node){4,x,a,y,b}; e[++e_size]=(node){4,x,a,y,b}; } e[++e_size]=(node){4,x,n+1,y,n+2}; e[++e_size]=(node){4,x,n+1,y,n+2}; e[++e_size]=(node){3,x,y,n+3}; e[++e_size]=(node){3,x,y,n+3}; } } printf("%d ",e_size); for1(1,e_size,i) { printf("%d %d %d %d",e[i].size,e[i].a,e[i].b,e[i].c); if(e[i].size==4) printf(" %d ",e[i].d); else printf(" "); } }