省選模擬26
阿新 • • 發佈:2022-03-05
小 G 的約數 小 G 的連通圖 小 G 的 DAG
且 \(L\) 為其他質數的倍數
A. 小 G 的約數
將給定的 \(n\) 分解質因數
按照每個因數含有的質因子次數和分類
答案就是最大的哪個
Code
#include<bits/stdc++.h> #define int long long//OVERFLOW !!! MEMORY LIMIT !!! #define rint signed #define inf 0x3f3f3f3f3f3f3f3f using namespace std; inline int read(){ int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();} return x*f; } int n,ans; int c[100010],cnt; int f[100010],siz; signed main(){ #ifdef LOCAL freopen("in","r",stdin); freopen("out","w",stdout); #endif freopen("divisor.in","r",stdin); freopen("divisor.out","w",stdout); n=read(); for(int i=2;i*i<=n;i++) if(n%i==0){cnt++;while(n%i==0) c[cnt]++,n/=i;}if(n!=1) c[++cnt]=1; sort(c+1,c+1+cnt);f[0]=1; for(int i=1;i<=cnt;i++){ for(int j=siz;~j;j--) for(int k=c[i];k;k--) f[j+k]+=f[j]; siz+=c[i]; } for(int i=1;i<=siz;i++) ans=max(ans,f[i]); printf("%lld\n",ans); return 0; }
B. 小 G 的連通圖
範圍小的可以暴力
範圍大的時候考慮構造一種方案
令 \(L=\prod_{i=1,i\ isprime}^{n}i\)
那麼他與除了 \(L+1\) 的所有數都相連
調整這種方法使得 \(L+1\) 也被連入集合
找一個 \(a\) 使得 \(L+1\) 與 \(L+a+1\) 相連
但這個時候 \(L\) 就不與 \(L+a\) 相連了
於是考慮再找一個 \(2a+1\)
這樣 \(l+a\) 就與 \(l+3a+1\) 相連,同時 \(l+1+a\) 也相連了
為了方便構造於是要求 \(a\) 和 \(2a+1\) 都是質數
最後得出 \(L\%a=a-1\) , \(L\%(2a+1)=a+1\)
\(CRT\) 合併一下就行,暴力列舉倍數也可以
Code
#include<bits/stdc++.h> #define int long long//OVERFLOW !!! MEMORY LIMIT !!! #define rint signed #define B 100000000 #define inf 0x3f3f3f3f3f3f3f3f using namespace std; inline int read(){ int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();} return x*f; } int n,A,mod,res,t,mu; int a[100010],len; int prime[100010],cnt; int ans[18]={2184,27829,27828,87890,87890,171054,171054,323510,127374,323510,151062,151062,151062,151061,151060,151059,151058,7106718}; bool is[100010]; inline void mul(int x){ for(int i=1;i<=len;i++) a[i]*=x; for(int i=1;i<=len;i++) if(a[i]>=B){ a[i+1]+=a[i]/B;a[i]%=B; if(i==len) len++; } } signed main(){ #ifdef LOCAL freopen("in","r",stdin); freopen("out","w",stdout); #endif freopen("graph.in","r",stdin); freopen("graph.out","w",stdout); n=read();a[1]=1,len=1; for(int i=2;i<=n;i++){ if(!is[i]) prime[++cnt]=i; for(int j=1;j<=cnt&&i*prime[j]<=n;j++){ is[i*prime[j]]=1; if(i%prime[j]==0) break; } } if(n<=16) puts("No solution"),exit(0); if(n<=35) printf("%lld\n",ans[n-17]),exit(0); for(int i=sqrt(n);i<=n;i++) if(i*i>n){ if(!is[i]&&!is[2*i+1]){A=i;break;} } mod=2*A*A+A,res=1; for(int i=1;i<=cnt;i++) if(prime[i]!=A&&prime[i]!=2*A+1) mul(prime[i]),res=res*prime[i]%mod; for(t=res,mu=1;t!=mod-3*A-1;t=(t+res)%mod,mu++); mul(mu);printf("%lld",a[len]);for(int i=len-1;i;i--) printf("%08lld",a[i]); return 0; }
C. 小 G 的 DAG
動態維護不好搞於是根號分治一下
對於 \(1\) 操作,每根號次就更新一次
對於 \(2\) 操作,發現查詢時只和上一次 \(1\) 操作後的值有關係
於是可以根號預處理一下,預處理操作完每個塊之後的最小值
那麼對於剩下的散塊直接暴力查詢
還剩下一個問題就是如何處理 \(x\) 能否到達 \(y\)
直接 \(bitset\) 開不下,於是可以每根號次操作處理一次,處理所有點能否到這根號次詢問的點
Code
#include<bits/stdc++.h>
#define int long long//OVERFLOW !!! MEMORY LIMIT !!!
#define rint signed
#define inf 0x3f3f3f3f3f3f3f3f
using namespace std;
inline int read(){
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){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 B=500;
int n,m,Q;
int bl[100010],L[100010],R[100010];
int deg[100010],a[100010],p;
int head[100010],ver[100010],to[100010],tot;
int v[100010],lst[100010];
int mn[100010][210],id[100010],t[100010];
bool is[100010];
pair<int,int>u[100010];
bitset<510>BT[100010];
queue<int>q;
inline void add(int x,int y){ver[++tot]=y;to[tot]=head[x];head[x]=tot;}
struct opt{int op,u,x;}LL[100010];
inline void upd(){for(int i=1,x;i<=n;i++){x=a[i];v[x]=u[x].first;lst[x]=u[x].second;for(int j=head[x];j;j=to[j]){int y=ver[j];if(u[x].second>u[y].second) u[y]=u[x];}}}
inline void topo(){for(int i=1;i<=n;i++) BT[i].reset();for(int i=n,x;i;i--){x=a[i];if(is[x]) BT[x][id[x]]=1;for(int j=head[x];j;j=to[j]){int y=ver[j];BT[x]|=BT[y];}}}
inline void umn(int blo){for(int i=1,x;i<=n;i++){x=a[i];for(int j=head[x];j;j=to[j]){int y=ver[j];v[y]=min(v[y],v[x]);}}for(int i=1;i<=n;i++) mn[i][blo]=v[i];}
inline void pre(){
for(int i=1;i<=bl[Q];i++){
for(int j=1;j<=n;j++) v[j]=inf;
for(int j=L[i];j<=R[i];j++) if(LL[j].op==2){
v[LL[j].u]=min(v[LL[j].u],LL[j].x);
}
umn(i);
}
}
inline int query(int x,int l,int r){
int res=inf;
if(bl[l]==bl[r]){
for(int i=l;i<=r;i++) if(LL[i].op==2) if(BT[LL[i].u][id[x]]) res=min(res,LL[i].x);
return res;
}
for(int i=l;i<=R[bl[l]];i++) if(LL[i].op==2) if(BT[LL[i].u][id[x]]) res=min(res,LL[i].x);
for(int i=L[bl[r]];i<=r;i++) if(LL[i].op==2) if(BT[LL[i].u][id[x]]) res=min(res,LL[i].x);
for(int i=bl[l]+1;i<=bl[r]-1;i++) res=min(res,mn[x][i]);
return res;
}
inline int getv(int x,int l,int r){
int res=v[x];
for(int i=l;i<=r;i++) if(LL[i].op==1){if(BT[LL[i].u][id[x]]) res=LL[i].x,lst[x]=i;}
return res;
}
signed main(){
#ifdef LOCAL
freopen("in","r",stdin);
freopen("out","w",stdout);
#endif
freopen("dag.in","r",stdin);
freopen("dag.out","w",stdout);
n=read(),m=read(),Q=read();for(int i=1;i<=Q;i++) bl[i]=(i-1)/B+1;
for(int i=1;i<=bl[Q];i++) L[i]=(i-1)*B+1,R[i]=min(i*B,Q);
for(int i=1,x,y;i<=m;i++){x=read(),y=read();add(x,y);deg[y]++;}
for(int i=1;i<=n;i++) if(!deg[i]) q.push(i);
while(!q.empty()){
int x=q.front();q.pop();a[++p]=x;
for(int i=head[x];i;i=to[i]){
int y=ver[i];deg[y]--;
if(!deg[y]) q.push(y);
}
}
for(int i=1;i<=Q;i++){LL[i].op=read(),LL[i].u=read();if(LL[i].op!=3) LL[i].x=read();}p=0;
for(int i=L[1];i<=R[1];i++) if(LL[i].op==3) is[LL[i].u]=1,t[id[LL[i].u]=++p]=LL[i].u;
topo();pre();
for(int i=1;i<=n;i++) v[i]=0;
for(int i=1,res;i<=Q;i++){
if(LL[i].op==1) u[LL[i].u]=make_pair(LL[i].x,i);
if(LL[i].op==3){
res=getv(LL[i].u,L[bl[i]],i);
res=min(res,query(LL[i].u,lst[LL[i].u],i));
printf("%lld\n",res);
}
if(i==R[bl[i]]){
for(int j=1;j<=p;j++) is[t[j]]=0;p=0;
for(int j=L[bl[i]+1];j<=R[bl[i]+1];j++) if(LL[j].op==3) is[LL[j].u]=1,t[id[LL[j].u]=++p]=LL[j].u;
topo();upd();
}
}
return 0;
}