数论基础 练习
Posted cxylsy
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数论基础 练习相关的知识,希望对你有一定的参考价值。
A - Bi-shoe and Phi-shoe(LightOJ - 1370)
这道题的题意是给队员购买竹子,每一个队员都有一个幸运数字,购买竹子的价格的欧拉值大于等于幸运数字。换一个说法就是找比给你的幸运数字大的最小的质数。数据范围100000。先打个质数表。然后暴力加起来就ok了。
1 #include<iostream> 2 using namespace std; 3 int a[1000005]; 4 void oula(){ 5 memset(a,0,sizeof(a)); 6 for(int i=2;i*i<=1000004;i++){ 7 if(!a[i]){ 8 for(int j=i+i;j<=1000004;j+=i){ 9 a[j]=1; 10 } 11 } 12 } 13 } 14 int main(){ 15 ios_base::sync_with_stdio(false), cout.tie(0), cin.tie(0); 16 oula(); 17 int t; 18 cin>>t; 19 int cas=0; 20 while(t--){ 21 int n; 22 cin>>n; 23 ll sum=0; 24 for(int i=0;i<n;i++) 25 { 26 int x; 27 cin>>x; 28 for(int j=x+1;;j++){ 29 if(!a[j]){ 30 sum+=j; 31 break; 32 } 33 } 34 } 35 cout<<"Case "<<++cas<<": "<<sum<<" Xukha"<<endl; 36 } 37 38 return 0; 39 }
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 ll p[1000100], prim[1000100]; 5 int k = 0; 6 void find_prim() 7 { 8 k = 0; 9 for(ll i = 2; i <= 1000000; i++) 10 { 11 if(!p[i]) 12 { 13 prim[k++] = i; 14 for(ll j = i+i; j <=1000000; j+=i) 15 { 16 p[j] = 1; 17 } 18 } 19 } 20 } 21 ll cont(ll a) 22 { 23 ll s = 1; 24 if(a == 0) 25 { 26 return 0; 27 } 28 ll tt = 0; 29 ll i = 0; 30 while(prim[i] < a && i < k) 31 { 32 tt = 0; 33 if(a%prim[i] == 0) 34 { 35 while(a%prim[i] == 0) 36 { 37 a/=prim[i]; 38 tt++; 39 } 40 } 41 s *= tt+1; 42 i++; 43 } 44 if(a > 1) 45 { 46 s *= 1+1; 47 } 48 return s; 49 } 50 int main() 51 { 52 ll a, b; 53 int t; 54 int cas = 0; 55 find_prim(); 56 scanf("%d",&t); 57 while(t--) 58 { 59 scanf("%lld%lld",&a,&b); 60 int cnt = 0; 61 ll num = 0, ans; 62 if(b >= sqrt(a)) 63 ans = 0; 64 else 65 { 66 for(ll i = 1; i < b; i++) 67 { 68 if(a%i == 0) 69 { 70 cnt++; 71 } 72 } 73 num = cont(a)/2; 74 ans = num - cnt; 75 } 76 printf("Case %d: %lld ",++cas,ans); 77 } 78 return 0; 79 }
1 #include<iostream> 2 using namespace std; 3 int main(){ 4 ios_base::sync_with_stdio(false), cout.tie(0), cin.tie(0); 5 int t; 6 cin>>t; 7 int cas=0; 8 while(t--){ 9 ll x; 10 cin>>x; 11 ll ans=(int)sqrt(x)+(int)sqrt(x/2); 12 cout<<"Case "<<++cas<<": "<<x-ans<<endl; 13 } 14 return 0; 15 }
E - Leading and Trailing
这道题求前n^k次方的前三位和后三位。后三位不用说直接跑快速幂取模,唯一的坑点是补0,如果最后三位为001也需要输出001。重点在于前三位怎么求。最开始也不会,网上看了代码。然后自己也推了一下公式,最后懂了。设p=log(n^k)->10^p=n^k->这个就会发现p的整数位数代表的是总的位数,而p的小数代表的就是每位数上的值。p=klogn,然后有一个东西叫做fmod(x,y)。这个函数能够得到小数部分,然后这道题就可以解决了。
1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 #include <algorithm> 5 #include <cmath> 6 #include <cstdlib> 7 #include <limits> 8 #include <queue> 9 #include <stack> 10 #include <vector> 11 #include <map> 12 13 using namespace std; 14 15 #define N 10005000 16 #define INF 0x3f3f3f3f 17 #define PI acos (-1.0) 18 #define EPS 1e-8 19 #define met(a, b) memset (a, b, sizeof (a)) 20 21 typedef long long LL; 22 23 int quickpow (int m, int n, int k) 24 { 25 int b = 1; 26 while (n > 0) 27 { 28 if (n & 1) 29 b = (b * m) % k; 30 n >>= 1; 31 m = (m * m) % k; 32 } 33 return b%k; 34 } 35 36 int main () 37 { 38 int t, flag = 1; 39 scanf ("%d", &t); 40 41 while (t--) 42 { 43 LL n, k; 44 scanf ("%lld %lld", &n, &k); 45 46 int first = pow (10.0, 2.0 + fmod (k*log10(n*1.0), 1)); 47 int last = quickpow (n%1000, k, 1000); 48 49 printf ("Case %d: %d %03d ", flag++, first, last); 50 } 51 return 0; 52 }
1 #include<cstdio> 2 #include<cstring> 3 #include<cstdlib> 4 #include<cctype> 5 #include<queue> 6 #include<cmath> 7 #include<string> 8 #include<map> 9 #include<stack> 10 #include<set> 11 #include<vector> 12 #include<iostream> 13 #include<algorithm> 14 #define INF 0x3f3f3f3f 15 #define ll long long 16 const int N=10000005; //18 17 const int MOD=1000; 18 using namespace std; 19 bool prime[N]; 20 int p[N/10],pn; 21 void get_prime(){ 22 pn=0; 23 memset(prime,false,sizeof(prime)); 24 prime[0]=prime[1]=true; 25 for(long long i=2;i<N;i++){ 26 if(!prime[i]){ 27 p[pn++]=i; 28 for(long long j=i*i;j<N;j+=i){ 29 prime[j]=true; 30 } 31 } 32 } 33 } 34 int main(){ 35 get_prime(); 36 int T,n,num=1,ans; 37 scanf("%d",&T); 38 while(T--){ 39 scanf("%d",&n); 40 ans=0; 41 for(int i=0;p[i]<=n/2;i++){ 42 if(prime[n-p[i]]==false) ans++; 43 } 44 printf("Case %d: %d ",num++,ans); 45 } 46 return 0; 47 }
1 #include<iostream> 2 using namespace std; 3 int main(){ 4 ios_base::sync_with_stdio(false), cout.tie(0), cin.tie(0); 5 int t; 6 cin>>t; 7 for(int i=1;i<=t;i++){ 8 ll m; 9 cin>>m; 10 int n=sqrt(m); 11 ll sum=0; 12 for(int i=1;i<=n;i++){ 13 sum+=(m/i-m/(i+1))*i+m/i; 14 } 15 if(m/n==n) 16 sum-=m/n; 17 cout<<"Case "<<i<<": "<<sum<<endl; 18 } 19 return 0; 20 }
H - Pairs Forming LCM
这道题的题意是给你一个n,满足题意的个数有多少,这道题也是唯一分解定理中的几个基本定理。将n唯一分解得到n=p1^e1*p2^e2*...*pn^en。然后我们就会发现lcm(i,j)=n,那么i,j的质因子分解必须满足max(iei,jei)=ei。然后我们就会发现,当i满足ei时,j就有ei种选择,同理j满足,i也有ei种,然后iei=jei=ei时又有一种所以需要在加一。所以总共的个数为sum=(e1*2+1)*(e2*2+1)*...*(en*2+1)。又因为j大于等于i,所以ans=sum/2,又因为i=j=n时这一种情况,所以还需要加一。最后的答案为ans=sum/2+1。
1 #include<stdio.h> 2 #include<string.h> 3 #include<stdlib.h> 4 #include<algorithm> 5 #include<stdio.h> 6 #include<string.h> 7 #include<stdlib.h> 8 #include<math.h> 9 #include<algorithm> 10 #include<iostream> 11 #include<vector> 12 #include<queue> 13 14 using namespace std; 15 typedef long long LL; 16 #define N 10010001 17 #define ESP 1e-8 18 #define INF 0x3f3f3f3f 19 #define memset(a,b) memset(a,b,sizeof(a)) 20 21 LL prime[1000000], k; 22 bool vis[N]; 23 24 void Prime() 25 { 26 memset(vis, false); 27 k = 0; 28 for(int i=2; i<N; i++) 29 { 30 if(vis[i] == 0) 31 { 32 prime[k ++] = i; 33 for(int j= i+i; j<N; j+=i) 34 { 35 vis[j] = 1; 36 } 37 } 38 } 39 } 40 41 LL solve(LL n) 42 { 43 LL ans, sum; 44 ans = 0; 45 sum = 1; 46 for(int i=0; prime[i] * prime[i] <= n; i++) 47 { 48 if(n%prime[i] == 0) 49 { 50 ans=0; 51 while(n%prime[i] == 0) 52 { 53 ans ++; 54 n /= prime[i]; 55 } 56 sum *= (2*ans+1); 57 } 58 } 59 if(n>1) 60 sum *= (2*1 + 1); 61 return sum; 62 } 63 64 int main() 65 { 66 int T, t=1; 67 LL n; 68 Prime(); 69 scanf("%d", &T); 70 while(T --) 71 { 72 LL n; 73 scanf("%lld", &n); 74 75 LL sum = solve(n); 76 77 printf("Case %d: %lld ", t++, sum/2+1); 78 } 79 return 0; 80 }
1 #include<iostream> 2 using namespace std; 3 double a[1000005]; 4 double C=0.57721566490153286060651209;//调和级数 n很大的时候 ans=logn+c+/(2*n); 5 void Init(){ 6 memset(a,0,sizeof(a)); 7 a[1]=1.0; 8 for(int i=2;i<=1000000;i++){ 9 a[i]=a[i-1]+1/(i*1.0); 10 } 11 } 12 int main(){ 13 ios_base::sync_with_stdio(false), cout.tie(0), cin.tie(0); 14 Init(); 15 int T, t=1; 16 cin>>T; 17 while(T --) 18 { 19 ll n; 20 cin>>n; 21 double ans; 22 if(n>1000000){ 23 ans=log(n)+C+1.0/(2*n); 24 } 25 else 26 ans=a[n]; 27 printf("Case %d: %.10f ", t++, ans); 28 } 29 30 return 0; 31 }
1 #include<iostream> 2 using namespace std; 3 int main(){ 4 ios_base::sync_with_stdio(false), cout.tie(0), cin.tie(0); 5 char s[205]; 6 ll n; 7 int t; 8 cin>>t; 9 int cas=0; 10 while(t--){ 11 cin>>s>>n; 12 if(n<0) 13 n=-n; 14 int t=strlen(s); 15 ll sum=0; 16 for(int i=0;i<t;i++){ 17 if(s[i]==‘-‘) 18 continue; 19 sum=(sum*10+s[i]-‘0‘)%n; 20 } 21 if(sum==0) 22 cout<<"Case "<<++cas<<": divisible"<<endl; 23 else 24 cout<<"Case "<<++cas<<": not divisible"<<endl; 25 } 26 27 return 0; 28 }
L - Fantasy of a Summation
这道题就是自己找规律,然后发现每个数出现的次数为n^(k-1)*k。然后将前n个数累加乘以n^(k-1)*k得到答案。
1 #include<iostream> 2 using namespace std; 3 int main(){ 4 ios_base::sync_with_stdio(false), cout.tie(0), cin.tie(0); 5 ll n,k,m; 6 int t; 7 cin>>t; 8 int cas=0; 9 while(t--){ 10 cin>>n>>k>>m; 11 int x; 12 ll sum=0; 13 for(int i=0;i<n;i++){ 14 cin>>x; 15 sum+=x; 16 sum%=m; 17 } 18 ll ans1=qpow(n,k-1,m)*k; 19 cout<<"Case "<<++cas<<": "<<(ans1*sum)%m<<endl; 20 } 21 22 return 0; 23 }
M - Help Hanzo
这道题是求两个数直接的质数有多少。首先对于任意的一个数n,他的最小质因数不会超过sqrt(n),那么就可以用[2,sqrt(n)]区间去筛掉[a,n]区间的约数,剩下的都是质数了,就是模拟区间筛法。
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int N = 1000005; 4 bool pri[N]; 5 int pri1[N]; 6 int sum=0; 7 long long l,r; 8 void Init(){ 9 memset(pri,true,sizeof(pri)); 10 pri[1]=pri[0]=false; 11 for(register int i=2;i<N;i++){ 12 if(pri[i]){ 13 pri1[sum++]=i; 14 for(register int j=0;j<sum&&i*pri1[j]<N;j++){ 15 pri[i*pri1[j]]=false; 16 if(!(i%pri1[j])) 17 break; 18 } 19 } 20 } 21 } 22 void Init1(){ 23 memset(pri,true,sizeof(pri)); 24 for(register long long i=0;i<sum;i++){ 25 long long b=l/pri1[i]; 26 while(b*pri1[i]<l||b<=1){ 27 b++; 28 } 29 for(register long long j=b*pri1[i];j<=r;j+=pri1[i]){ 30 if(j>=l){ 31 pri[j-l]=false; 32 } 33 } 34 if(l==1) 35 pri[0]=false; 36 } 37 } 38 int main(){ 39 Init(); 40 int t; 41 scanf("%d",&t); 42 int cas=0; 43 while(t--){ 44 scanf("%lld%lld",&l,&r); 45 Init1(); 46 long long ans=0; 47 for(int i=0;i<=r-l;i++){ 48 if(pri[i]) 49 ans++; 50 } 51 printf("Case %d: %lld ",++cas,ans); 52 } 53 return 0; 54 }
1 #include<iostream> 2 using namespace std; 3 ll sum(ll n){ 4 ll ans=0; 5 while(n){ 6 ans+=n/5; 7 n/=5; 8 } 9 return ans; 10 } 11 int main(){ 12 ios_base::sync_with_stdio(false), cout.tie(0), cin.tie(0); 13 int t; 14 cin>>t; 15 int cas=0; 16 while(t--){ 17 ll x; 18 cin>>x; 19 // cout<<x<<endl; 20 ll l=0,r=10000000000; 21 ll ans=0; 22 while(l<=r){ 23 ll mid=(l+r)>>1; 24 if(sum(mid)==x){ 25 ans=mid; 26 r=mid-1; 27 } 28 else if(sum(mid)>x){ 29 r=mid-1; 30 } 31 else{ 32 l=mid+1; 33 } 34 } 35 // cout<<ans<<endl; 36 if(ans){ 37 printf("Case %d: %lld ",++cas,ans); 38 } 39 else 40 printf("Case %d: impossible ",++cas); 41 } 42 43 return 0; 44 }
1 //XDDDDDDi 2 #include <iostream> 3 #include <string> 4 #include <cstdio> 5 #include <cstdlib> 6 #include <sstream> 7 #include <iomanip> 8 #include <map> 9 #include <stack> 10 #include <deque> 11 #include <queue> 12 #include <vector> 13 #include <set> 14 #include <list> 15 #include <cstring> 16 #include <cctype> 17 #include <algorithm> 18 #include <iterator> 19 #include <cmath> 20 #include <bitset> 21 #include <ctime> 22 #include <fstream> 23 #include <limits.h> 24 #include <cassert> 25 #include <climits> 26 #include <complex> 27 #include <streambuf> 28 #include <typeinfo> 29 #include <new> 30 /* 31 #include <array> 32 #include <numeric> 33 #include <unordered_map> 34 #include <unordered_set> 35 #include <random> 36 #include <tuple> 37 */ 38 using namespace std; 39 40 #define PB push_back 41 #define MP make_pair 42 #define MT make_tuple 43 #define pii pair<int,int> 44 #define pdd pair<double,double> 45 #define F first 46 #define S second 47 #define mian main 48 #define ture true 49 50 #define MAXN 1000000+5 51 #define MOD 1000000007 52 #define PI (acos(-1.0)) 53 #define EPS 1e-6 54 #define MMT(s,a) memset(s, a, sizeof s) 55 #define GO(i,a,b) for(int i = (a); i < (b); ++i) 56 #define GOE(i,a,b) for(int i = (a); i <= (b); ++i) 57 #define OG(i,a,b) for(int i = (a); i > (b); --i) 58 #define OGE(i,a,b) for(int i = (a); i >= (b); --i) 59 typedef unsigned long long ull; 60 typedef long long ll; 61 typedef double db; 62 typedef long double ldb; 63 typedef stringstream sstm; 64 const int INF = 0x3f3f3f3f; 65 int fx[4][2] = {1,0,-1,0,0,1,0,-1}; 66 67 /* 68 template<typename T> 69 using maxHeap = priority_queue<T, vector<T>, less<T> >; 70 template<typename T> 71 using minHeap = priority_queue<T, vector<T>, greater<T> >; 72 */ 73 74 template<typename T> 75 inline T gcd(T a, T b){ return b==0 ? a : gcd(b,a%b); } 76 template<typename T> 77 inline T lowbit(T x){ return x&(-x); } 78 template<typename T> 79 inline bool mishu(T x){ return x>0?(x&(x-1))==0:false; } 80 inline char nc(){ static char buf[1000000], *p1 = buf, *p2 = buf; return p1 == p2 && (p2 = (p1 = buf) + fread(buf,1,1000000,stdin),p1 == p2) ? EOF : *p1++; } 81 #define nc getchar 82 template<typename T> 83 inline int read(T& sum){ char ch = nc(); if(ch == EOF || ch == -1) return 0; int tf = 0; sum = 0; while((ch < ‘0‘ || ch > ‘9‘) && (ch != ‘-‘)) ch = nc(); tf = ((ch == ‘-‘) && (ch = nc())); while(ch >= ‘0‘ && ch <= ‘9‘) sum = sum*10 + (ch-48), ch = nc(); (tf) && (sum = -sum); return 1; } 84 template<typename T> 85 inline void print(T k){ int num = 0,ch[20]; if(k == 0){ putchar(‘0‘); return ; } (k<0)&&(putchar(‘-‘),k = -k); while(k>0) ch[++num] = k%10, k /= 10; while(num) putchar(ch[num--]+48); } 86 /*math*/ 87 template<typename T1,typename T2, typename T3> 88 ll qmul(T1 a,T2 b,T3 p){ ll w = 0; while(b){ if(b&1) w = (w+a)%p; b>>=1; a = (a+a)%p; } return w; } 89 template<typename T1,typename T2, typename T3> 90 ll qpow(T1 a,T2 b,T3 p){ ll w = 1; while(b){ if(b&1) w = (qmul(w,a,p))%p; b>>=1; a = (qmul(a,a,p))%p;} return w; } 91 template<typename T> 92 ll exgcd(T a, T b, T& x, T& y){ if(b == 0){ x = 1, y = 0; return (ll)a; } ll r = exgcd(b,a%b,y,x); y -= a/b*x; return r;/*gcd*/ } 93 94 /* ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- */ 95 int a[1000005]; 96 void oula(){ 97 memset(a,0,sizeof(a)); 98 for(int i=2;i*i<=1000004;i++){ 99 if(!a[i]){ 100 for(int j=i+i;j<=1000004;j+=i){ 101 a[j]=1; 102 } 103 } 104 } 105 } 106 int main(){ 107 ios_base::sync_with_stdio(false), cout.tie(0), cin.tie(0); 108 oula(); 109 int t; 110 cin>>t; 111 int cas=0; 112 while(t--){ 113 int n; 114 cin>>n; 115 // cout<<a[2]<<endl; 116 ll sum=0; 117 for(int i=0;i<n;i++) 118 { 119 int x; 120 cin>>x; 121 for(int j=x+1;;j++){ 122 if(!a[j]){ 123 // cout<<j<<‘ ‘; 124 sum+=j; 125 break; 126 } 127 } 128 } 129 cout<<"Case "<<++cas<<": "<<sum<<" Xukha"<<endl; 130 } 131 132 return 0;
以上是关于数论基础 练习的主要内容,如果未能解决你的问题,请参考以下文章