9.23 NOIP模拟题(数学专练)

                                                        数论基础 专题测试 


                                                                                                                                                            命题人:清华大学 王赢绪

/*
水题
答案为C(n-k,m-1)  预处理阶乘和逆元,O(1)算答案 
开始读错题了!!!朱一乐!!! 
*/
#include<iostream>
#include<cstdio>
#include<cstring>

#define N 1000003
#define mod 1000000007
#define ll long long

using namespace std;
ll fac[N]={1,1},inv[N]={1,1},f[N]={1,1};
ll n,m,k,ans,cnt;

inline ll read()
{
    ll x=0,f=1;char c=getchar();
    while(c>'9'||c<'0'){if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
    return x*f;
}

inline int C(ll a,ll b)
{
    if(a<b) return 0;
    return fac[a]*inv[b]%mod*inv[a-b]%mod;
}

inline void init()
{
    for(int i=2;i<N;i++)
    {
        fac[i]=fac[i-1]*i%mod;
        f[i]=(mod-mod/i)*f[mod%i]%mod;
        inv[i]=inv[i-1]*f[i]%mod; 
    }
}

int main()
{
    freopen("ball.in","r",stdin);
    freopen("ball.out","w",stdout);
    n=read();m=read();k=read();
    init();
    ans=C(n-k,m-1);    
    printf("%I64d
",ans%mod);
    fclose(stdin);fclose(stdout);
    return 0;
}

 

 

 

#include<iostream>
#include<cstdio>
#include<cstring>

#define N 10000001
#define ll long long

using namespace std;
ll n,t,m,ans,cnt,tot;
ll phi[N+10],prime[N+10];
bool mark[N+10];

void getphi()
{
    phi[1]=1;mark[1]=1;
    for(int i=2;i<=n;i++)
    {
        if(!mark[i]) prime[++tot]=i,phi[i]=i-1;
        for(int j=1;j<=tot;j++)
        {
            if(i*prime[j]>n) break;
            mark[i*prime[j]]=1;
            if(i%prime[j]==0)
            {
                phi[i*prime[j]]=phi[i]*prime[j];break;
            }
            else phi[i*prime[j]]=phi[i]*(prime[j]-1);
        }
    }
}

ll gcd(ll a,ll b){return b==0?a:gcd(b,a%b);}

int main()
{
    freopen("gcd.in","r",stdin);
    freopen("gcd.out","w",stdout);
    scanf("%d",&t);scanf("%d",&n);
    if(t==1)
    {
        getphi();
        ans=0;
        for(int i=2;i<=n;i++)
        ans+=phi[i];
        printf("%d
",ans*2+1);
    }
    else if(n<10000)
    {
        getphi();
        ans=0;
        for(int i=1;i<=n;i++)
          for(int j=1;j<=n;j++)
            {
                int no=gcd(i,j);
                if(!mark[no]) ans++;
            }
        printf("%d
",ans);
    }
    if(t==2 && n==10000)
    {
        printf("27497027
");
        return 0;
    }
    return 0;
}
80暴力

 

#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>

using namespace std;

typedef long long int64;
const int MAXN=10000005;

int T,n;
int top,prm[MAXN];
int64 phi[MAXN];
bool vis[MAXN];
int64 ans;

int main()
{
    freopen ("gcd.in","r",stdin);
    freopen ("gcd.out","w",stdout);
    cin>>T>>n;
    phi[1]=1;
    for (int i=2;i<=n;i++)
    {
        if (!vis[i]) prm[++top]=i,phi[i]=i-1;
        for (int j=1;j<=top&&i*prm[j]<=n;j++)
        {
            vis[i*prm[j]]=true;
            if (i%prm[j]==0)
            {
                phi[i*prm[j]]=phi[i]*prm[j];
                break;
            }
            else phi[i*prm[j]]=phi[i]*(prm[j]-1);
        }
    }
    if (T==1)
    {
        for (int i=1;i<=n;i++) ans+=phi[i];
        ans=2*ans-1;
    }
    if (T==2)
    {
        for (int i=2;i<=n;i++) phi[i]+=phi[i-1];
        for (int i=1;i<=top;i++) ans+=phi[n/prm[i]]*2-1;    
    }
    cout<<ans<<endl;
    return 0;
}

 

 

 

题解:

 

/*
这题好到没话说 
*/
#include <cmath>
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <cstdlib>
#include <algorithm>

using namespace std;

typedef long long int64;
const int MAXN=10000005;

int prm[MAXN/10];
bool vis[MAXN];
int64 phi[MAXN];
int ti[MAXN],ys[MAXN];
int MOD;

int64 pw(int64 x,int64 y)
{
    int64 res=1;
    for (;y;y>>=1)
    {
        if (y&1) res=(res*x)%MOD;
        x=(x*x)%MOD;
    }
    return res;
}

void exgcd(int64 a,int64 b,int64 &xx,int64 &yy)
{
    if (!b)
    {
        xx=1;
        yy=0;
        return;
    }
    int64 x1,x2;
    exgcd(b,a%b,x1,x2);
    xx=x2;
    yy=x1-(a/b)*x2;
}

void pre_prime_3()
{
    int top=0;
    phi[1]=1;
    for (int i=2;i<=10000000;i++)
    {
        if (!vis[i]) prm[++top]=i,phi[i]=i-1;
        for (int j=1;j<=top&&i*prm[j]<=10000000;j++)
        {
            vis[i*prm[j]]=true;
            if (i%prm[j]==0)
            {
                phi[i*prm[j]]=phi[i]*prm[j];
                break;
            }
            phi[i*prm[j]]=phi[i]*(prm[j]-1);
        }
    }
}

void pre_prime_4()
{
    int top=0;
    ys[1]=1;
    for (int i=2;i<=10000000;i++)
    {
        if (!vis[i]) prm[++top]=i,ys[i]=2,ti[i]=1;
        for (int j=1;j<=top&&i*prm[j]<=10000000;j++)
        {
            vis[i*prm[j]]=true;
            if (i%prm[j]==0)
            {
                ys[i*prm[j]]=ys[i]/(ti[i]+1)*(ti[i]+2);
                ti[i*prm[j]]=ti[i]+1;
                break;
            }
            ys[i*prm[j]]=ys[i]*ys[prm[j]];
            ti[i*prm[j]]=1;
        }
    }
}

void work1()
{
    int T,a,b;
    int64 x,y;
    scanf("%d",&T);
    while (T--)
    {
        scanf("%d%d",&a,&b);
        exgcd(a,b,x,y);
        x=(x%b+b)%b;
        printf("%d
",(int)x);
    }
}

void work2()
{
    int T;
    scanf("%d",&T);
    while (T--)
    {
        int a,ans=2000000000;
        scanf("%d%d",&a,&MOD);
        int p=(int)sqrt(MOD-1);
        for (int i=1;i<=p;i++)
        {
            if ((MOD-1)%i!=0) continue;
            if (pw(a,i)==1) ans=min(ans,i);
            if (pw(a,(MOD-1)/i)==1) ans=min(ans,(MOD-1)/i);
        }
        printf("%d
",ans);
    }
}

void work3()
{
    pre_prime_3();
    for (int i=1;i<=10000000;i++) phi[i]+=phi[i-1];
    int T,n,m;
    int64 ans;
    scanf("%d",&T);
    while (T--)
    {
        ans=0;
        scanf("%d%d",&n,&m);
        if (n>m) swap(n,m);
        int last;
        for (int i=1;i<=n;i=last+1)
        {
            int nn=n/i,mm=m/i;
            nn=n/nn,mm=m/mm;
            last=min(nn,mm);
            ans+=(phi[last]-phi[i-1])*(n/i)*(m/i);
        }
        printf("%lld
",ans);
    }
}

void work4()
{
    pre_prime_4();
    for (int i=1;i<=10000000;i++) ys[i]+=ys[i-1];
    int T,n;
    scanf("%d",&T);
    while (T--)
    {
        scanf("%d",&n);
        printf("%d
",ys[n]);
    }
}

int main()
{
    freopen ("years.in","r",stdin);
    freopen ("years.out","w",stdout);
    int sub_task;
    scanf("%d",&sub_task);
    if (sub_task==1) work1();
    if (sub_task==2) work2();
    if (sub_task==3) work3();
    if (sub_task==4) work4();
    return 0;
}

 

 

 

折花枝,恨花枝,准拟花开人共卮,开时人去时。 怕相思,已相思,轮到相思没处辞,眉间露一丝。
原文地址:https://www.cnblogs.com/L-Memory/p/7582955.html