noip模擬26
阿新 • • 發佈:2021-07-28
T1 神炎皇 T2 降雷皇 T3 幻魔皇
,線性篩尤拉函式,篩到\(\sqrt n\),複雜度\(O(\sqrt n)\)
期望得分:60+100+40=200
實際得分:60+100+40=200
T1 整個\(O(n^2)\)的就20了,然後因為時間沒到,就接著推,還有打表。
然後發現,gcd(a,b)=d時, a=xd , b=yd ,想要滿足 \((a+b)|ab,即(x+y)d|xyd^2\),需要滿足 \((x+y)|d\)。
然後設 (x+y)k=d,那麼使 \((x+y)^2k\),滿足小於n就行了,答案就是 \(\frac{n}{{(x+y)}^2}\)。
這個的複雜度是 \(O(n^2 \sqrt n)\),但是列舉到對答案沒有貢獻 break 掉就行了,準確是在 \(x+y=\sqrt n\),這個時候60pts。
其實不用列舉,因為大小相等的(x+y)對答案的貢獻都一樣,並且若 x,y互質,那麼x,y和(x+y)也互質,設 x+y=k ,對數就是 \(\phi(k)\)
T2 權值線段樹維護最長長度和其數量,單點修改,區間查詢
T3 求樹上距離,找lca,只有兩種情況,lca為兩個白點中的一個,或者是一個黑的。第一種情況,列舉所有長度,在深度合法的白色節點向下找 i 步。第二種情況,因為有兩顆子樹,那就在深度合法的黑色節點向下分別找 i和 j步
T1
#include<bits/stdc++.h> using namespace std; const int N=1e7+11; long long n; int sl; long long phi[N],p[N]; bool fp[N]; void oula() { long long ss=sqrt(n); fp[0]=1; fp[1]=1; for(int i=2;i<=ss;i++) { if(!fp[i]) { phi[i]=i-1; p[++sl]=i; } for(int j=1;j<=sl&&p[j]*i<=ss;j++) { fp[i*p[j]]=1; if(i%p[j]==0) { phi[i*p[j]]=phi[i]*p[j]; break; } else phi[i*p[j]]=phi[i]*(p[j]-1); } } return; } int main() { cin>>n; oula(); long long ans=0; int k=sqrt(n); for(long long i=1;i<=k;i++) ans+=phi[i]*(n/(i*i)); printf("%lld\n",ans); return 0; }
T2
#include<bits/stdc++.h> using namespace std; const int N=100011; const long long mod=123456789; struct tree{ int l,r; int len; long long num; }tre[5*N]; int n,ty; int xl[N],lsh[N]; inline int read() { int s=0; int w=1; char ch=getchar(); while(ch>'9'||ch<'0') { if(ch=='-') w=-1; ch=getchar(); } while(ch>='0'&&ch<='9') { s=(s<<1)+(s<<3)+(ch^48); ch=getchar(); } return s*w; } void build(int i,int l,int r) { tre[i].l=l; tre[i].r=r; if(l==r) return; int mid=(l+r)>>1; build(i<<1,l,mid); build(i<<1|1,mid+1,r); return; } void updata(int i) { if(tre[i<<1].len==tre[i<<1|1].len) { tre[i].num=tre[i<<1].num+tre[i<<1|1].num; tre[i].num%=mod; tre[i].len=tre[i<<1].len; } else { if(tre[i<<1].len>tre[i<<1|1].len) { tre[i].len=tre[i<<1].len; tre[i].num=tre[i<<1].num; } else { tre[i].len=tre[i<<1|1].len; tre[i].num=tre[i<<1|1].num; } } return; } tree query(int i,int x) { tree ans1,ans2; ans2.len=ans1.len=0; ans2.num=ans1.num=0; if(tre[i].l==tre[i].r) { if(tre[i].l<=x) return tre[i]; return ans1; } if(tre[i].r<=x) return tre[i]; else { int mid=(tre[i].l+tre[i].r)>>1; if(mid+1>x) return query(i<<1,x); else { ans1=query(i<<1,x); ans2=query(i<<1|1,x); if(ans1.len==ans2.len) { ans1.num+=ans2.num; ans1.num%=mod; return ans1; } else { if(ans1.len>ans2.len) return ans1; else return ans2; } } } return ans1; } void insert(int i,int x,tree ans) { if(tre[i].l==tre[i].r) { if(x==tre[i].l) { if(!ans.num) ans.num++; if(tre[i].len==ans.len) ans.num+=tre[i].num; tre[i].num=ans.num; tre[i].num%=mod; tre[i].len=ans.len; } return; } int mid=(tre[i].l+tre[i].r)>>1; if(mid>=x) insert(i<<1,x,ans); else insert(i<<1|1,x,ans); updata(i); return; } void lsh_() { sort(lsh+1,lsh+n+1); int x=unique(lsh+1,lsh+n+1)-lsh; for(int i=1;i<=n;i++) xl[i]=lower_bound(lsh+1,lsh+x,xl[i])-lsh; return; } int main() { n=read(); ty=read(); for(int i=1;i<=n;i++) lsh[i]=xl[i]=read(); lsh_(); build(1,1,n); for(int i=1;i<=n;i++) { tree ans=query(1,xl[i]-1); ans.len++; insert(1,xl[i],ans); } cout<<tre[1].len<<endl; if(ty) cout<<tre[1].num%mod<<endl; return 0; }
T3
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=100011;
const int mod=123456789;
int n;
int f[N];
int sum[N];
int ans[N];
void pre()
{
f[1]=f[2]=1;
sum[1]=1;
sum[2]=2;
for(int i=3;i<=n;i++)
{
f[i]=(f[i-1]+f[i-2])%mod;
sum[i]=(sum[i-1]+f[i])%mod;
}
return;
}
signed main()
{
cin>>n;
pre();
for(int i=2;i<n-1;i++)
ans[i]=f[i-1]*(sum[n-i-2]+1)%mod;
ans[n-1]=f[n-2];
for(int i=2;i<n;i++)
{
for(int j=3;j<n;j++)
ans[i+j]=(ans[i+j]+sum[n-max(i,j)-1]*f[i-1]%mod*f[j-2])%mod;
ans[i+1]=(ans[i+1]+sum[n-i-1]*f[i-1]%mod)%mod;
}
for(int i=1;i<=2*n;i++)
printf("%lld ",ans[i]);
return 0;
}