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; }
#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; }
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; }
#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); }
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; } } }
#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); }