zoukankan      html  css  js  c++  java
  • 数学

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

    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;
    }
  • 相关阅读:
    C#中页面之间跳转方法比较
    C#中web页面之间传递数组参数
    js跳转传递参数
    枚举
    js操作做GridView
    数据库登录问题汇总
    数据库登录遇到的问题
    关于配置服务器(IIS7)(二)
    关于配置服务器(IIS7)
    使用JavaScript设置、获取父子页面中的值
  • 原文地址:https://www.cnblogs.com/xiaoxubi/p/6429304.html
Copyright © 2011-2022 走看看