数学

学校内部的数学小测,真·爆零

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;
}
原文地址:https://www.cnblogs.com/xiaoxubi/p/6429304.html