学校内部的数学小测,真·爆零
T1
题意:
sol :首先,∀x,φ(x)=1或偶数,所以最终答案即为进行φ操作下x的因子中2的个数
又因为φ(p^q)=(p-1)*φ(p^(q-1))
定义num[i]为φ操作下i的因子中2的个数,则num[i]={num[i-1],i为质数
,i不为质数
若原式为,#define n N (逃~)
则对原式的每一个p进行上述操作(预处理num数组),然后即可求得n=∑num[pi]*qi
//by:std #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; const int maxn=1000100; int cnt[maxn]; int pr[maxn],tot; bool vis[maxn]; inline void pre(int n){ pr[tot++]=2; cnt[2]=1; cnt[4]=2; vis[4]=true; for (int i=3;i<=n;++i){ if (!vis[i]){ pr[tot++]=i; cnt[i]=cnt[i-1]; } for (int j=0;j<tot&&pr[j]*i<=n;++j){ vis[pr[j]*i]=true; cnt[pr[j]*i]=cnt[pr[j]]+cnt[i]; if (i%pr[j]==0) break; } } return; } int main(){ freopen("first.in","r",stdin); freopen("first.out","w",stdout); pre(100000); int T=0,n,a,b; scanf("%d",&T); while(T--){ scanf("%d",&n); if (n==0){ puts("0"); continue; } long long ans=0; while(n--){ scanf("%d%d",&a,&b); if (a==2) ans+=b-1; else ans+=(long long)b*cnt[a]; } printf("%lld ",ans+1); } fclose(stdout); return 0; }
T2
题意:
sol :
第一问:首先求出每个位置的值得期望
对于每次交换,因为是随机的,所以其他所有节点的概率是相等的
定义self[x]表示交换x次后到自己的概率,self[0]=1,self[1]=0
递推式为self[i+j]=(self[i]*self[j])+(1-self[i])*(1-self[j])/(n-1),倍增处理,只记录self[2^j]的值
则点i的期望点权num[i]为self[i]*val[i]+(sum-val[i])*(1-self[i])/(n-1)
对于任意区间,考虑点i被选到的概率p[i]为i*(n-i+1)/(C(n,2)+n)
ans即为∑num[i]*p[i]
第二问:可以求出任意堆的期望合并次数
定义f[i]为还剩i个堆时任意堆的期望合并次数
f[i]=(2/i)*(f[i-1]+1)+(1-(2/i))*(f[i-1]),即f[i]=f[i-1]+(2/i)
所以ans=f[n]*sum
//by:std #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; const int maxn=100100,mod=1000000007; int n; long long m; int aa[maxn]; long long power(long long a,int b){ long long ret=1; while(b){ if (b&1) ret=ret*a%mod; b>>=1; a=a*a%mod; } return ret; } namespace task1{ inline void mul(long long &a,long long &b,long long c,long long d){ long long x,y; x=(a*c%mod+b*d%mod*(n-1)%mod)%mod; y=(a*d%mod+b*c%mod+b*(n-2)%mod*d%mod)%mod; a=x; b=y; return; } long long solve(){ long long ret=0; long long sel=1,oth=0; long long change=power((long long)n*(n-1)/2%mod,mod-2),nchange=(1-change*(n-1)%mod+mod)%mod; while(m){ if (m&1) mul(sel,oth,nchange,change); mul(nchange,change,nchange,change); m>>=1; } long long sum=0; for (int i=1;i<=n;++i) (sum+=aa[i])%=mod; long long inv=power(((long long)n*(n-1)/2+n)%mod,mod-2); for (int i=1;i<=n;++i){ long long p=(long long)i*(n-i+1)%mod*inv%mod; (ret+=p*oth%mod*(sum-aa[i]+mod))%=mod; (ret+=p*sel%mod*aa[i])%=mod; } return ret; } } namespace task2{ long long f[maxn]; long long solve(){ f[1]=0; for (int i=2;i<=n;++i){ long long p=2*power(i,mod-2); f[i]=(p+f[i-1])%mod; } long long ret=0; for (int i=1;i<=n;++i) (ret+=f[n]*aa[i])%=mod; return ret; } } int main(){ freopen("second.in","r",stdin); freopen("second.out","w",stdout); scanf("%d%lld",&n,&m); for (int i=1;i<=n;++i) scanf("%d",&aa[i]); cout<<task1::solve()<<endl; scanf("%d",&n); for (int i=1;i<=n;++i) scanf("%d",&aa[i]); cout<<task2::solve()<<flush; fclose(stdout); return 0; }
T3
题意:
sol :考虑将两个∑交换一下,则式子可化为
对于每块相等的分块,快速计算∑d(j)
设D(x)表示∑(i<=x) d(i),即
再将∑交换,化为∑(j<=x)
//by:std #include<ctime> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; const int maxn=21544347; int pr[maxn/10],cnt[maxn],tot; bool vis[maxn]; int d[maxn]; // long long tt=0; inline long long calc(long long n){ if (n<maxn) return d[n]; long long ret=0; for (long long st=1;st<=n;){ long long ed=n/(n/st); ret+=(n/st)*(ed-st+1); st=ed+1; // ++tt; } return ret; } inline void pre(){ d[1]=1; for (int i=2;i<maxn;++i){ if (!vis[i]){ pr[tot++]=i; d[i]=2; cnt[i]=1; } for (int j=0;j<tot&&i*pr[j]<maxn;++j){ int k=i*pr[j]; vis[k]=true; if (i%pr[j]==0){ cnt[k]=cnt[i]+1; d[k]=d[i]/(cnt[i]+1)*(cnt[k]+1); } else{ cnt[k]=1; d[k]=d[i]*2; } } } for (int i=2;i<maxn;++i) d[i]+=d[i-1]; return; } int main(){ freopen("third.in","r",stdin); freopen("third.out","w",stdout); pre(); // cout<<clock()<<endl; long long n; scanf("%lld",&n); // n=100000000000LL; long long ans=0,lst=0; for (long long st=1,ed;st<=n;st=ed+1){ // ++tt; ed=n/(n/st); long long tmp=calc(ed); ans+=(n/st)*(tmp-lst); lst=tmp; } // cout<<clock()<<endl; printf("%lld",ans); // cout<<endl<<tt<<endl; fclose(stdout); return 0; }