4.5考试
众所周知,只要考数学和概率与期望,lyh就会挂大分,尤其是概率与期望……
考试总结
一、答题策略
考场不知道咋回事,没有想出来B题就挺可惜的……
看到概率与期望大脑都是蒙的……根本没想策略,导致答题时非常慌张。
嗯,下次答题时还是不能心态炸掉……
二、题解
A.[JLOI2014] 聪明的燕姿
纯数学题。
根据整数的唯一分解定理(\(x=\prod\limits_{i=1}^kp_i^{a_i}\))和约数和公式(\(S=\prod\limits_{i=1}^k(\sum\limits_{j=0}^{a_i}p_i^j)\)),我们可以尝试暴搜。
\(dfs(x,y,s)\) 表示还有 \(x\) 可以分解,枚举到了第 \(y\) 个质数,当前的答案是多少。
当 \(x=p+1\) 时,\(ans\) 可以是 \(s\times p\);
当 \(x=1\) 时,\(ans\) 可以是 \(s\)。
时间复杂度没细算,是 \(O(能过)\)。
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=1e5+5;
int n,m,k,v[N];
ll p[N],ans[N];
int pr(ll x){
if(x==1) return 0;
for(int i=2;i*i<=x;i++)
if(x%i==0) return 0;
return 1;
}void dfs(ll x,int y,ll s){
if(x==1){
ans[++k]=s;
return;
}if(pr(x-1)&&x>p[y])
ans[++k]=s*(x-1);
for(int i=y;p[i]*p[i]<=x;i++){
ll l=p[i],j=p[i]+1;
for(;j<=x;l*=p[i],j+=l)
if(x%j==0) dfs(x/j,i+1,s*l);
}
}int main(){
for(int i=2;i<N;i++){
if(!v[i]) p[++n]=i;
for(int j=1;j<=n&&p[j]*i<N;j++){
v[i*p[j]]=1;
if(i%p[j]==0) break;
}
}while(cin>>m){
dfs(m,1,1);
sort(ans+1,ans+k+1);
cout<<k<<"\n";
for(int i=1;i<=k;i++)
cout<<ans[i]<<" ";
if(k) k=0,cout<<"\n";
}return 0;
}
B.luogu P4550
概率与期望题。
先考虑次数的期望。设 \(f_i\) 表示抽到了 \(i\) 种不同邮票的期望次数,则有:
化简得:
设 \(g_i\) 表示抽到了 \(i\) 种不同邮票的期望钱数,则有:
化简得:
时间复杂度 \(O(n)\)。
#include<bits/stdc++.h>
#define ll long long
using namespace std;
double n,dp[10005],f[10005];
int main(){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
cin>>n;
for(int i=n-1;~i;i--){
dp[i]=dp[i+1]+n/(n-i);
f[i]=(double)i/(n-i)*dp[i]+f[i+1]+dp[i+1]+n/(n-i);
}printf("%.2lf",f[0]);
return 0;
}
C.[HAOI2018] 苹果树
难于上青天……
考虑拆开来考虑每一条边的贡献。
答案即为 \(\sum\operatorname{size}(i)(n-\operatorname{size}(i))\)。
设 \(dp_{i,j,k}\) 表示子树根节点为 \(i\),决策到 \(k\) 号点,\(i\) 的子树大小为 \(j\),则有:
于是 \(i\) 就被我们抛弃了。
所以我们只需要
即可。时间复杂度 \(O(n^2)\)。
#include<bits/stdc++.h>
#define ll long long
using namespace std;
ll n,p,dp[2005][2005],jc[2005],ans;
int main(){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
cin>>n>>p;
jc[0]=1;
for(ll i=1;i<=n;i++){
jc[i]=jc[i-1]*i%p;
for(ll j=1;j<=i;j++)
dp[i][j]=(dp[i-1][j-1]*j%p+dp[i-1][j]*(i-j-1)%p)%p;
dp[i][1]=(dp[i][1]+jc[i])%p;
}for(ll i=1;i<=n;i++)
ans=(ans+dp[n][i]*i*(n-i)%p)%p;
cout<<ans;
return 0;
}
D.[HAOI2012] 高速公路
由于实际上只有 \(n-1\) 条公路,所以每次询问的 \(r=r-1\)。
容易看得出,每一个询问的答案为:
设分子为 \(ans\),则:
设 \(s1=a_i,s_2=a_ii,s_3=a_ii^2\):
\(s1,s2,s3\) 可以用线段树维护,在修改 \(s2,s3\) 时,需要统计 \(s4=\sum i,s5=\sum i^2\)。
时间复杂度 \(O(n\log n)\)。
#include<bits/stdc++.h>
#define int long long
using namespace std;
int gcd(int x,int y){
if(!y) return x;
return gcd(y,x%y);
}const int N=4e5+5;
int n,m,lf[N],rt[N],lb[N];
int a[N],b[N],c[N],d[N],e[N];
int s1,s2,s3;
void down(int x,int k){
a[x]+=(rt[x]-lf[x]+1)*k;
b[x]+=k*d[x];
c[x]+=k*e[x];
lb[x]+=k;
}void pushdown(int x){
if(!lb[x]) return;
down(x*2,lb[x]);
down(x*2+1,lb[x]);
lb[x]=0;
}void build(int l,int r,int x){
lf[x]=l,rt[x]=r;
if(l==r){
d[x]=l;
e[x]=l*l;
return;
}int mid=(l+r)/2;
build(l,mid,x*2);
build(mid+1,r,x*2+1);
d[x]=d[x*2]+d[x*2+1];
e[x]=e[x*2]+e[x*2+1];
}void chg(int l,int r,int x,int v){
if(l<=lf[x]&&rt[x]<=r){
down(x,v);
return;
}pushdown(x);
int mid=(lf[x]+rt[x])/2;
if(mid>=l) chg(l,r,x*2,v);
if(mid<r) chg(l,r,x*2+1,v);
a[x]=a[x*2]+a[x*2+1];
b[x]=b[x*2]+b[x*2+1];
c[x]=c[x*2]+c[x*2+1];
}void que(int l,int r,int x){
if(l<=lf[x]&&rt[x]<=r){
s1+=a[x];
s2+=b[x];
s3+=c[x];
return;
}pushdown(x);
int mid=(lf[x]+rt[x])/2;
if(mid>=l) que(l,r,x*2);
if(mid<r) que(l,r,x*2+1);
}signed main(){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
cin>>n>>m;
build(1,n-1,1);
while(m--){
char c;
cin>>c;
if(c=='C'){
int l,r,v;
cin>>l>>r>>v;
chg(l,r-1,1,v);
continue;
}int l,r;
s1=s2=s3=0;
cin>>l>>r;
que(l,r-1,1);
int x=(r-r*l)*s1+(r+l-1)*s2-s3;
int y=(r-l+1)*(r-l)/2;
int g=gcd(x,y);
cout<<x/g<<"/"<<y/g<<"\n";
}return 0;
}