學校內部的數學小測,真·爆零ios
T1數組
題意:spa
sol :首先,∀x,φ(x)=1或偶數,因此最終答案即爲進行φ操做下x的因子中2的個數code
又由於φ(p^q)=(p-1)*φ(p^(q-1))blog
定義num[i]爲φ操做下i的因子中2的個數,則num[i]={num[i-1],i爲質數 數學
,i不爲質數string
若原式爲,#define n N (逃~)it
則對原式的每個p進行上述操做(預處理num數組),而後便可求得n=∑num[pi]*qiio
//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\n",ans+1); } fclose(stdout); return 0; }
T2class
題意:
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; }