大菜鸡的数论之旅-[kuangbin带你飞]专题十四 数论基础
A题 LightOJ 1370 Bi-shoe and Phi-shoe
Problem Description
Bamboo Pole-vault is a massively popular sport in Xzhiland. And Master Phi-shoe is a very popular coach for his success. He needs some bamboos for his students, so he asked his assistant Bi-Shoe to go to the market and buy them. Plenty of Bamboos of all possible integer lengths (yes!) are available in the market. According to Xzhila tradition,Score of a bamboo = Φ (bamboo’s length)
(Xzhilans are really fond of number theory). For your information, Φ (n) = numbers less than n which are relatively prime (having no common divisor other than 1) to n. So, score of a bamboo of length 9 is 6 as 1, 2, 4, 5, 7, 8 are relatively prime to 9.
The assistant Bi-shoe has to buy one bamboo for each student. As a twist, each pole-vault student of Phi-shoe has a lucky number. Bi-shoe wants to buy bamboos such that each of them gets a bamboo with a score greater than or equal to his/her lucky number. Bi-shoe wants to minimize the total amount of money spent for buying the bamboos. One unit of bamboo costs 1 Xukha. Help him.
Input
Input starts with an integer T (≤ 100), denoting the number of test cases.
Each case starts with a line containing an integer n (1 ≤ n ≤ 10000) denoting the number of students of Phi-shoe. The next line contains n space separated integers denoting the lucky numbers for the students. Each lucky number will lie in the range [1, 106].
Output
For each case, print the case number and the minimum possible money spent for buying the bamboos. See the samples for details.
Sample Input
3
5
1 2 3 4 5
6
10 11 12 13 14 15
2
1 1
Sample Output
Case 1: 22 Xukha
Case 2: 88 Xukha
Case 3: 4 Xukha
----------------------------------------------------分割线-----------------------------------------------------------------------
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e6+5;
int num[10005];
int pr[N],phi[N];
bool f[N];
void init()
{
int i,j,k,p=0;
phi[1]=1;
for(i=2; i<N; ++i)
{
if(!f[i])
phi[pr[++p]=i]=i-1;
for(j=1; j<=p&&(k=i*pr[j])<N; ++j)
{
f[k]=1;
if(i%pr[j])
phi[k]=phi[i]*(pr[j]-1);
else
{
phi[k]=phi[i]*pr[j];
break;
}
}
}
}
int main()
{
init();
int T;
scanf("%d",&T);
for(int cas=1;cas<=T;cas++)
{
int n;
scanf("%d",&n);
ll ans=0;
for(int i=1;i<=n;i++)
{
scanf("%d",&num[i]);
for(int j=max(num[i],2);j<N;j++)
{
if(phi[j]>=num[i])
{
ans+=j;
break;
}
}
}
printf("Case %d: %lld Xukha\n",cas,ans);
}
return 0;
}
B题不见了~
C题 LightOJ 1341 Aladdin and the Flying Carpet
Problem Description
It’s said that Aladdin had to solve seven mysteries before getting the Magical Lamp which summons a powerful Genie. Here we are concerned about the first mystery.
Aladdin was about to enter to a magical cave, led by the evil sorcerer who disguised himself as Aladdin’s uncle, found a strange magical flying carpet at the entrance. There were some strange creatures guarding the entrance of the cave. Aladdin could run, but he knew that there was a high chance of getting caught. So, he decided to use the magical flying carpet. The carpet was rectangular shaped, but not square shaped. Aladdin took the carpet and with the help of it he passed the entrance.
Now you are given the area of the carpet and the length of the minimum possible side of the carpet, your task is to find how many types of carpets are possible. For example, the area of the carpet 12, and the minimum possible side of the carpet is 2, then there can be two types of carpets and their sides are: {2, 6} and {3, 4}.
Input
Input starts with an integer T (≤ 4000), denoting the number of test cases.
Each case starts with a line containing two integers: a b (1 ≤ b ≤ a ≤ 1012) where a denotes the area of the carpet and b denotes the minimum possible side of the carpet.
Output
For each case, print the case number and the number of possible carpets.
Sample Input
2
10 2
12 2
Sample output
Case 1: 1
Case 2: 2
代码
#include <bits/stdc++.h>
using namespace std;
const int N = 1e6+7;
typedef long long ll;
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define per(i,a,b) for(int i=a;i>=b;i--)
bool vis[N];
int prime[N];
int cnt;
void sieve(ll n)
{
int m=(int)sqrt(n+0.5);
memset(vis,0,sizeof(vis));
rep(i,2,m)
{
if(!vis[i])
{
for (int j=i*i; j<=n; j+=i)
vis[j]=1;
}
}
}
int gen_primes(int n)
{
sieve(n);
int c=0;
for(int i=1; i<=n; i++)
if(!vis[i])
prime[c++]=i;
return c;
}
int main()
{
cnt=gen_primes(N-1);
int T,kase=0;
scanf("%d",&T);
while(T--)
{
ll a, b;
scanf("%lld%lld",&a,&b);
ll ans=1;
if(b>=sqrt(a))
{
printf("Case %d: %d\n",++kase,0);
continue;
}
else
{
ll tmp=a;
for (int i=1;i<cnt&&1ll*prime[i]*prime[i]<=a;i++)
{
if (a%prime[i]==0)
{
int num=0;
while(a%prime[i]==0)
{
num++;
a/=prime[i];
}
ans*=(num+1);
}
}
if(a>1)
ans*=2;
ans/=2;
for(int i=1;i<b;i++)
if (tmp%i==0)
ans--;
}
printf("Case %d: %lld\n",++kase,ans);
}
return 0;
}
D题 LightOJ 1336 Sigma Function
Problem Description
Sigma function is an interesting function in Number Theory. It is denoted by the Greek letter Sigma (σ). This function actually denotes the sum of all divisors of a number. For example σ(24) = 1+2+3+4+6+8+12+24=60. Sigma of small numbers is easy to find but for large numbers it is very difficult to find in a straight forward way. But mathematicians have discovered a formula to find sigma. If the prime power decomposition of an integer is
Then we can write,
For some n the value of σ(n) is odd and for others it is even. Given a value n, you will have to find how many integers from 1 to n have even value of σ.
Input
Input starts with an integer T (≤ 100), denoting the number of test cases.
Each case starts with a line containing an integer n (1 ≤ n ≤ 1012).
Output
For each case, print the case number and the result.
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define per(i,a,b) for(int i=a;i>=b;i--)
const int N=10005;
int main()
{
int T;
scanf("%d",&T);
rep(cas,1,T)
{
ll n;
scanf("%lld",&n);
printf("Case %d: %lld\n",cas,n-(int)sqrt(n)-(int)sqrt(n/2));
}
return 0;
}
E题 LightOJ 1282 Leading and Trailing
Problem Description
You are given two integers: n and k, your task is to find the most significant three digits, and least significant three digits of nk.
Input
Input starts with an integer T (≤ 1000), denoting the number of test cases.
Each case starts with a line containing two integers: n (2 ≤ n < 231) and k (1 ≤ k ≤ 107).
Output
For each case, print the case number and the three leading digits (most significant) and three trailing digits (least significant). You can assume that the input is given such that nk contains at least six digits.
Sample Input
5
123456 1
123456 2
2 31
2 32
29 8751919
Sample Output
Case 1: 123 456
Case 2: 152 936
Case 3: 214 648
Case 4: 429 296
Case 5: 665 669
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define per(i,a,b) for(int i=a;i>=b;i--)
ll quick_pow(ll a, ll b, ll p)
{
ll ans=1;
a%=p;
while(b)
{
if(b&1) ans=ans*a%p;
a=a*a%p;
b>>=1;
}
return ans;
}
ll cal(ll n,ll k,int dig)
{
return pow(10.0,dig+fmod((double)k*log10((double)n),1));
}
int main()
{
int T;
scanf( "%d",&T);
rep(cas,1,T)
{
int n,k;
scanf("%d%d",&n,&k);
printf("Case %d: %lld %03lld\n",cas,cal(n,k,2),quick_pow(n,k,1000));
}
return 0;
}
F题 LightOJ 1259 Goldbach`s Conjecture
Problem Description
Goldbach’s conjecture is one of the oldest unsolved problems in number theory and in all of mathematics. It states:
Every even integer, greater than 2, can be expressed as the sum of two primes [1].
Now your task is to check whether this conjecture holds for integers up to 107.
Input
Input starts with an integer T (≤ 300), denoting the number of test cases.
Each case starts with a line containing an integer n (4 ≤ n ≤ 107, n is even).
Output
For each case, print the case number and the number of ways you can express n as sum of two primes. To be more specific, we want to find the number of (a, b) where
-
Both a and b are prime
-
a + b = n
-
a ≤ b
Sample Input
2
6
4
Sample Output
Case 1: 1
Case 2: 1
Note
An integer is said to be prime, if it is divisible by exactly two different integers. First few primes are 2, 3, 5, 7, 11, 13, …
代码
#include <bits/stdc++.h>
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define per(i,a,b) for(int i=(a);i>=(b);i--)
using namespace std;
typedef long long ll;
const int N=1e6+5;
const int MAXN=1e7+5;
int pre[N];
bool check[MAXN];
int tot=0;
void init()
{
memset(check,0,sizeof(check));
for(int i=2; i<=MAXN; i++)
{
if(!check[i])
pre[tot++]=i;
for(int j=0; j<tot&&pre[j]*i<=MAXN; ++j)
{
check[i*pre[j]]=1;
if(i%pre[j]==0)
break;
}
}
}
int main()
{
init();
int T;
scanf("%d",&T);
rep(cas,1,T)
{
int n;
scanf("%d",&n);
int cnt=0;
int ans=0;
while(pre[cnt]<=n/2&&cnt<tot)
{
if(check[n-pre[cnt]]==false)
{
ans++;
}
cnt++;
}
printf("Case %d: %d\n",cas,ans);
}
return 0;
}
----------------------------------------分割线-----------------------------------------------------------------------------------