數學

學校內部的數學小測,真·爆零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;
}
相關文章
相關標籤/搜索