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\n",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\n",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\n",ans); } if(t==2 && n==10000) { printf("27497027\n"); return 0; } return 0; }
#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\n",(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\n",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\n",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\n",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; }
折花枝,恨花枝,准拟花开人共卮,开时人去时。
怕相思,已相思,轮到相思没处辞,眉间露一丝。