Ordered partition problem
Consider such a conclusion: if the set obtained by a partition can be divided into two groups, and the maximum value of all numbers contained in one group is less than the minimum value of all numbers in the other set, it is not satisfied that the partition is ordered, otherwise it is ordered
The necessity of formalization is to prove that the successor of each point in the ring arrangement is considered. Let the set of the part with the smallest maximum in the above expression be \ (S \), then the successor of the set in each \ (S \) on the ring belongs to \ (S \), and the combination of the set that does not belong to \ (S \) cannot form a ring arrangement
The way to construct the legal ring arrangement is to sort all the divided sets according to the minimum value, and try to join the ring arrangement one by one
Let these \ (m \) sets be sorted from small to large according to the minimum value, and the result is \ (a {q_1} \ dots a {q_m} \)
The set \ (a {Q _1} \ dots a {Q _k} \) is currently joined and attempts to join \ (a {Q {K + 1} \). If you cannot find a \ (a {Q J} \) in this line segment, where the maximum value is greater than the minimum value of \ (a {Q {K + 1} \), because the minimum value of the following set is larger, it can be divided into two parts
So far, consider which set each number from \ (1 \) to \ (n \) belongs to in the partition, and some of them can no longer be added to numbers
Set \ (dp_{i,j,k} \) to indicate that you are trying to add \ (I \), and \ (j \) sets have been added to the partition, of which \ (k \) can no longer be added. Transfer the partition to create a new set or not. The implementation needs to scroll the array
Another way is to exclude several dividing lines. The transfer coefficient is a negative Stirling number. You can even use two-dimensional divide and conquer FFT to \ (\ Theta(n^2\log^2n) \)
Code Displayconst int N=510; int n,m,dp[2][N][N]; signed main(){ freopen("partition.in","r",stdin); freopen("partition.out","w",stdout); n=read(); m=read(); int cur=0; dp[0][0][0]=1; for(int i=1;i<=n;++i){ for(int j=0;j<=n;++j){ for(int k=0;k<=j;++k){ if(k==0&&i!=n) continue; if(j>0){ dp[cur^1][j][k]=dp[cur][j-1][k]; if(k>0) ckadd(dp[cur^1][j][k],dp[cur][j-1][k-1]); } if(k<=j) ckadd(dp[cur^1][j][k],mul(dp[cur][j][k+1],k+1)); ckadd(dp[cur^1][j][k],mul(dp[cur][j][k],k)); } } for(int j=0;j<=n;++j){ for(int k=0;k<=j;++k) dp[cur][j][k]=0; } cur^=1; } print(dp[cur][m][0]); return 0; }
Euler function
Maintain std::bitset with segment tree and use it_ Find_ first,_ Find_ Just next
\(\ rm poly \log \) calculates the set of prime factors for each number \ (I \), adds a point with a weight of \ (w=1-\frac{1}p \) at \ ((i,i) \) in the two-dimensional plane for a \ (prime|i \), finds the position of the last occurrence \ (K \) and the position of the next occurrence \ (j \), and adds a point with a weight of \ (\ frac 1w \) at points \ ((k,i) \) and \ ((i,j) \)
According to this structure, the information for solving \ ([l,r] \) is the product of all point weights of \ (x \ Ge, l, y \ Le, R \)
If it becomes a simple three bit partial order, you can cdq divide and conquer. For the remaining interval sum and interval product, use \ (\ rm Fenwick\ Tree \)
If forced online, KD tree can be used to achieve root complexity without \ (\ log \)
Code Displayconst int N=1e6+10,M=5e4+10; int Q,a[M],n,pri[N],cnt; bool fl[N]; struct BIT{ int c[N]; inline void push_add(int x,int v){ for(;x<=n;x+=x&(-x)) c[x]+=v; return ; } inline void push_mul(int x,int v){ for(;x<=n;x+=x&(-x)) ckmul(c[x],v); return ; } inline int query_sum(int x){ int res=0; for(;x;x-=x&(-x)) res+=c[x]; return res; } inline int query_mul(int x){ int res=1; for(;x;x-=x&(-x)) ckmul(res,c[x]); return res; } }Tsum,Tmul; int inv[40010]; bitset<4400>st[M<<2]; inline void push_up(int x){ st[x]=st[x<<1]|st[x<<1|1]; return ; } inline void build(int p,int l,int r){ if(l==r){ int x=a[l]; for(int i=1;x>1;++i) if(x%pri[i]==0){ st[p][i]=1; while(x%pri[i]==0) x/=pri[i]; } return ; }int mid=(l+r)>>1; build(p<<1,l,mid); build(p<<1|1,mid+1,r); return push_up(p); } bitset<4400>upd; inline void Modify(int p,int l,int r,int pos){ if(l==r) return st[p]=upd,void(); int mid=(l+r)>>1; if(pos<=mid) Modify(p<<1,l,mid,pos); else Modify(p<<1|1,mid+1,r,pos); return push_up(p); } inline void Query(int p,int l,int r,int ql,int qr){ if(ql<=l&&r<=qr) return upd|=st[p],void(); int mid=(l+r)>>1; if(ql<=mid) Query(p<<1,l,mid,ql,qr); if(qr>mid) Query(p<<1|1,mid+1,r,ql,qr); return ; } inline int Get_phi(int x){ int ans=x; for(int i=1;i<=cnt&&pri[i]*pri[i]<=x;++i) if(x%pri[i]==0){ while(x%pri[i]==0) x/=pri[i]; ans=ans/pri[i]*(pri[i]-1); } if(x>1) ans=ans/x*(x-1); return ans; } signed main(){ freopen("phi.in","r",stdin); freopen("phi.out","w",stdout); n=1e6; for(int i=2;i<=n;++i){ if(!fl[i]) pri[++cnt]=i; for(int j=1;j<=cnt&&1ll*i*pri[j]<=n;++j){ fl[i*pri[j]]=1; if(i%pri[j]==0) break; } } n=4e4; inv[1]=inv[0]=1; for(int i=2;i<=n;++i) inv[i]=mod-mul(mod/i,inv[mod%i]); n=read(); Q=read(); rep(i,1,n) a[i]=read(),Tsum.push_add(i,a[i]),Tmul.c[i]=1; rep(i,1,n) Tmul.push_mul(i,a[i]); build(1,1,n); while(Q--){ int opt=read(); if(opt==0){ int i=read(),v=read(); upd.reset(); int x=v; for(int i=1;x>1;++i) if(x%pri[i]==0){ upd[i]=1; while(x%pri[i]==0) x/=pri[i]; } Modify(1,1,n,i); Tsum.push_add(i,v-a[i]); Tmul.push_mul(i,mul(v,inv[a[i]])); a[i]=v; }else if(opt==1){ int l=read(),r=read(); print(Get_phi(Tsum.query_sum(r)-Tsum.query_sum(l-1))); }else{ int l=read(),r=read(); int ans=mul(ksm(Tmul.query_mul(l-1),mod-2),Tmul.query_mul(r)); upd.reset(); Query(1,1,n,l,r); for(int i=upd._Find_first();i!=4400;i=upd._Find_next(i)){ ckmul(ans,del(1,inv[pri[i]])); } print(ans); } } return 0; }
Upper circle of dot integer
The pre knowledge is LOJ3069. You can get 60 points by directly changing the code
The calculation method of scaling is to construct a mapping of \ (n \) prime factor set \ (D \) to non negative integers, which can also be understood as maintaining the occurrence times of each factor of \ (n \) in the process of min25 screening
The initial state of this mapping process is similar to directly finding the point value at the prime number of the function. Find out whether \ (n \) contains the factor \ (2k+1\left(k\in[0,+\infty]\right) \). If there is \ (1 \), then there is \ (0 \)
The addition of the function is the contraposition addition, and the multiplication is the Dirichlet convolution. All the rest is given to the min25 sieve
Special attention should be paid to the implementation here. Due to the maintenance mapping, the complexity is more than one \ (d(n)\log d(n) \, and the convolution implementation with square will be stuck
Some ideas during the game are to use block playing table, which is relatively poor. It can't run out in two and a half hours. One possible way is to use multi-threaded playing table
Code Displayconst int N=1e6+10; int cnt_d,id1[N],id2[N],Div[100],mp[10000],k,tot; ll n,m,R[N],g1[N],g3[N],bl; bool fl[N]; int pri[N],cnt,s1[N],s3[N]; vector<int> js[20]; struct Poly{ ll a[18]; Poly(){memset(a,0,sizeof a);} Poly operator+(const Poly &b)const{ Poly c; for(int i=0;i<cnt_d;++i) c.a[i]=a[i]+b.a[i]; return c; } Poly operator-(const Poly &b)const{ Poly c; for(int i=0;i<cnt_d;++i) c.a[i]=a[i]-b.a[i]; return c; } Poly operator *(const Poly &b)const{ Poly c; for(int i=0;i<cnt_d;++i){ for(auto j:js[i]){ c.a[mp[Div[i]*Div[j]]]+=a[i]*b.a[j]; } } return c; } Poly operator *(const ll &b)const{ Poly c; for(int i=0;i<cnt_d;++i) c.a[i]=a[i]*b; return c; } }one,three,zero; inline int get_id(ll x){ if(x>m) return -1; return mp[x]; } inline int id(ll x){return x<=bl?id1[x]:id2[n/x];} inline Poly calc(ll n,int x){ if(n<pri[x]) return zero; Poly res=one*(g3[id(n)]-s3[x-1])+three*(g1[id(n)]-s1[x-1]); /* according to the formula of Min25 algorithm: variable res should be initalized with this value */ for(int j=x;1ll*pri[j]*pri[j]<=n;++j){ int tim=1; ll prd=pri[j]; while(prd<=n){ Poly ret=calc(n/prd,j+1); if(tim>1) ret=ret+one; if(pri[j]%4==1){ Poly fpow; int vv=get_id(2*tim+1); if(~vv) fpow.a[vv]=1,res=res+fpow*ret; }else res=res+one*ret; tim++; prd*=pri[j]; } } return res; } signed main(){ // freopen("1.in","r",stdin); freopen("jozb.in","r",stdin); freopen("jozb.out","w",stdout); n=2e5; for(int i=2;i<=n;++i){ if(!fl[i]){ pri[++cnt]=i; s1[cnt]=s1[cnt-1]; s3[cnt]=s3[cnt-1]; if(i%4==3) s3[cnt]++; if(i%4==1) s1[cnt]++; } for(int j=1;j<=cnt&&1ll*i*pri[j]<N;++j){ fl[i*pri[j]]=1; if(i%pri[j]==0) break; } } memset(mp,-1,sizeof(mp)); n=read(); m=read(); bl=sqrt(n); if(m%4||m>8748) puts("0"),exit(0); m/=4; for(int i=1;i<=m;++i) if(m%i==0) Div[cnt_d]=i,mp[i]=cnt_d++; one.a[0]=1; int ee=get_id(3); if(~ee) three.a[ee]=1; for(int i=0;i<cnt_d;++i){ for(int j=0;j<cnt_d;++j) if(m%(Div[i]*Div[j])==0) js[i].pb(j); } if(cnt_d>18) puts("0"),exit(0); for(ll l=1,r;l<=n;l=R[tot]+1){ R[++tot]=n/(n/l); g1[tot]=(R[tot]-1)/4; g3[tot]=(R[tot]+1)/4; if(R[tot]<=bl) id1[R[tot]]=tot; else id2[n/R[tot]]=tot; } rep(i,2,cnt){ if(1ll*pri[i]*pri[i]>n) break; if(pri[i]%4==1){ for(int j=tot;1ll*pri[i]*pri[i]<=R[j];--j){ int x=id(R[j]/pri[i]); g1[j]-=g1[x]-s1[i-1]; g3[j]-=g3[x]-s3[i-1]; } }else{ for(int j=tot;1ll*pri[i]*pri[i]<=R[j];--j){ int x=id(R[j]/pri[i]); g1[j]-=g3[x]-s3[i-1]; g3[j]-=g1[x]-s1[i-1]; } } } Poly res=calc(n,1); print(res.a[mp[m]]+(m==1)*2); return 0; }