zoukankan      html  css  js  c++  java
  • 2017-9-22 NOIP模拟赛[xxy][数论]

    XXY 的 的 NOIP 模拟赛 4 4 —— 数学专场


    A

    Description
    定义 f(x)表示 x 的约数和,例:f(12)=1+2+3+4+6+12=28
    给出 x,y,求Σf(i),i∈[x,y]
    Input
    一行两个整数 x,y
    Output
    一行表示答案
    Example
    两组输入数据
    2 4
    123 321
    对应输出
    14
    72543
    Hint
    对于 20%的数据,1<=x<=y<=1000
    对于 40%的数据,1<=x<=y<=1e7
    对于 100%的数据,1<=x<=y<=2e9

    #include<iostream>
    #include<cstdio>
    using namespace std;
    long long x,y;
    long long count(int x){
        long long res=0;
        long long l=1,r;
        while(1){
            r=x/(x/l);
            long long a=x/l;
            res+=((l+r)*(r-l+1)/2)*a;
            l=r+1;
            if(x/l==0)break;
        }
        return res;
    }
    int main(){
        freopen("A.in","r",stdin);
        freopen("A.out","w",stdout);
        cin>>x>>y;
        long long ansl=count(x-1);
        long long ansr=count(y);
        cout<<ansr-ansl;
    }
    90分 出现整数被0除的错误
    #include<iostream>
    #include<cstdio>
    using namespace std;
    long long x,y;
    long long count(int x){
        long long res=0;
        long long l=1,r;
        while(1){
            if(x/l==0)r=x;
            else r=x/(x/l);
            long long a=x/l;
            res+=((l+r)*(r-l+1)/2)*a;
            l=r+1;
            if(x/l==0)break;
        }
        return res;
    }
    int main(){
        freopen("A.in","r",stdin);
        freopen("A.out","w",stdout);
        cin>>x>>y;
        long long ansl=count(x-1);
        long long ansr=count(y);
        cout<<ansr-ansl;
    }
    100分

    B

    Description
    求满足以下条件的 x 的个数
    ① x∈[1,n!]
    ② 设 pi 为质数且 pi|x,那么 pi>m,对于所有的 pi 均成立
    答案对 100000007 取模
    Input
    一行两个整数 n,m
    Output
    一行表示答案
    Example
    3 组输入样例
    100 10
    100 20
    10000 9000
    Output
    对应 3 组输出
    43274465
    70342844
    39714141
    Hint
    对于 20%的数据,n,m<=8
    对于 60%的数据,n<=100000,m<=8
    对于 100%的数据,n<=10000000,保证 n-m<=100000,m<=n

    学到的一点东西

    1.x的所有素因子大于m,则x与m!互素
    2.已知phi[(i-1)!],递推地求phi[i!]
      如果i是素数,phi[i!]=phi[(i-1)!]*(i-1)
      如果i不是素数,phi[i!]=phi[(i-1)!]*i

    3.phi[n!]=phi[m!]*(n!/m!)

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    using namespace std;
    int p[10000],n,m,w=1,ans,cnt;
    bool vis[10000000],q[1000000];
    void dfs(int pos,long long sum){
        if(sum>w)return;
        if(!q[sum]&&sum!=1)ans++,q[sum]=1;
        //cout<<sum<<' ';
        for(int i=pos;i<=cnt;i++){
            if(sum*p[i]>w)return;
            dfs(i,sum*p[i]);
        }
    }
    int main(){
        //freopen("Cola.txt","r",stdin);
        freopen("B.in","r",stdin);
        freopen("B.out","w",stdout);
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)w*=i;
        for(int i=2;i<=w;i++){
            if(!vis[i])p[++cnt]=i;
            for(int j=1;j<=cnt&&i*p[j]<=w;j++){
                vis[i*p[j]]=1;
                if(i%p[j]==0)break;
            }
        }
        int pos=upper_bound(p+1,p+cnt+1,m)-p;
        dfs(pos,1);
        for(int i=pos;i<=cnt;i++){
            if(cnt>w)break;
            if(!q[p[i]])ans++;
        }
        cout<<ans;
    }
    20分 暴力
    #include<cstdio>
    #define N 10000001
    #define mod 100000007
    using namespace std;
    int cnt,p[664580],phi[N];
    long long phifac[N];
    bool v[N];
    int main()
    {
        freopen("B.in","r",stdin);
        freopen("B.out","w",stdout);
        phi[1]=1;
        for(int i=2;i<N;i++)
        {
            if(!v[i])
            {
                p[++cnt]=i;
                phi[i]=i-1;
            }
            for(int j=1;j<=cnt;j++)
            {
                if(i*p[j]>=N) break;
                v[i*p[j]]=true;
                if(i%p[j]) phi[i*p[j]]=phi[i]*(p[j]-1);
                else
                {
                    phi[i*p[j]]=phi[i]*p[j];
                    break;
                }
            }
        }
        int n,m; long long ans;
        scanf("%d%d",&n,&m);
            ans=0;
            phifac[1]=1;
            for(int i=2;i<=m;i++) 
            if(!v[i]) phifac[i]=phifac[i-1]*(i-1)%mod;
            else phifac[i]=phifac[i-1]*i%mod;
            ans=phifac[m];
            for(int i=m+1;i<=n;i++) ans=ans*i%mod;
            printf("%I64d
    ",ans-1);
    }
    100分

    C

    Description
    令 f(k)=n 表示 有 n 种方式,可以把正整数 k 表示成几个素数的乘积的形式。
    例 10=2*5=5*2,所以 f(10)=2
    给出 n,求最小的 k
    Input
    一行一个整数 n
    Output
    一行表示答案
    Example
    四组输入样例
    1
    2
    3
    105
    对应输出:
    2
    6
    12
    720
    Hint
    20%的数据,k<=20
    另外 20%的数据,n<=20
    另外 20%的数据,k<=1e6
    100%的数据,k,n<=2^60

    #include<iostream>
    #include<cstdio>
    using namespace std;
    long long a[50];
    int k,n,bin[1000],p[100000],cnt;
    bool vis[1000000];
    bool check(int x){
        int l=0,pos=1;
        while(x!=1){
            while(x%p[pos]!=0)pos++;
            l=l+1;
            bin[l]=0;
            while(x%p[pos]==0){
                bin[l]++;
                x=x/p[pos];
            }
        }
        long long res=1;
        int sum=0;
        for(int i=1;i<=l;i++)sum+=bin[i];
        res=a[sum];
        for(int i=1;i<=l;i++)res/=a[bin[i]];
        if(res==n)return 1;
        return 0;
    }
    int main(){
        //freopen("Cola.txt","r",stdin);
        freopen("C.in","r",stdin);
        freopen("C.out","w",stdout);
        a[1]=1;
        for(int i=2;i<=25;i++)a[i]=a[i-1]*i;
        scanf("%d",&n);
        for(int i=2;i<=100000;i++){
            if(!vis[i])p[++cnt]=i;
            for(int j=1;j<=cnt&&i*p[j]<=100000;j++){
                vis[i*p[j]]=1;
                if(i%p[j]==0)break;
            }
        }
        for(int i=2;i<=100000;i++){//k的所有可能值 
            if(check(i)){
                printf("%d",i);
                return 0;
            }
        }
    }
    30分 暴力枚举答案
    #include<cstdio>
    #include<iostream>
    using namespace std;
    typedef  long long LL;
    int p[21]={0,2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71};
    LL ans,n;
    LL C[70][70];
    void solve(int num,int lim,LL tot,LL now,int last)
    {
        if(now>ans) return;
        if(tot==n) { ans=now; return ; }
        if(tot>n || num>20) return;
        LL t=1;
        for(int i=1;i<=lim;i++)
        {
            t*=p[num];
            if(now>=ans/t) return;
            solve(num+1,i,tot*C[last+i][i],now*t,last+i);
        }
    }
    int main()
    {
        freopen("C.in","r",stdin);
        freopen("C.out","w",stdout);
        C[0][0]=1;
        for(int i=1;i<70;i++)
        {
            C[i][0]=1;
            for(int j=1;j<=i;j++)
                C[i][j]=C[i-1][j-1]+C[i-1][j];
        } 
        scanf("%I64d",&n);
        if(n==1)
        {
               printf("1 2
    ");
               return 0;
        }
        ans=(LL)1<<60;
        solve(1,63,1,1,0);
        printf("%I64d
    ",ans);
    }
    100分 搜索+剪枝
  • 相关阅读:
    标准化组织 相关术语
    c++大作业五子棋-需求分析与设计方案
    [转载] ZooKeeper简介
    [转载] Netty源码分析
    [转载] Netty教程
    [转载] Java NIO与IO
    [转载] Java NIO教程
    [转载] 文件锁(Filelock)与锁定映射文件部分内容
    [转载] Java集合框架之小结
    [转载] 运维角度浅谈:MySQL数据库优化
  • 原文地址:https://www.cnblogs.com/thmyl/p/7574982.html
Copyright © 2011-2022 走看看