HDU4135 HDU2841 HDU1695 求[1,m]中与n互素的数的个数
求n的質因子
模板:求1-m之間與n互素的數的個數
vector<ll>p; //返回1-m中與n互素的數的個數 ll cal(ll n,ll m) {p.clear();for(int i=2;i*i<=n;i++){if(n%i==0){p.push_back(i);while(n%i==0) n/=i;}}if(n>1) p.push_back(n);//求n的素因子int num=p.size();//素因子的個數int maxs=1<<num;//從中選出一些質因子,就是生成子集,子集最多的個數ll s=0;//1到m中與n不互素的數的個數//枚舉子集,不能有空集,所以從1開始for(ll i=1;i<maxs;i++){//從1枚舉到(2^素因子個數)ll cnt=0;ll mul=1;for(ll j=0;j<num;j++){//枚舉每個素因子if(i&(1<<j)){//有第i個因子cnt++;//計數mul*=p[j];//乘上這個質因子}}//容斥原理if(cnt&1) //選取個數為奇數,加s+=m/mul;else //選取個數為偶數,減s-=m/mul;}return m-s;//返回1-m中與n互素的數的個數 }HDU4135
Given a number N, you are asked to count the number of integers between A and B inclusive which are relatively prime to N.?
Two integers are said to be co-prime or relatively prime if they have no common positive divisors other than 1 or, equivalently, if their greatest common divisor is 1. The number 1 is relatively prime to every integer.
Input
The first line on input contains T (0 < T <= 100) the number of test cases, each of the next T lines contains three integers A, B, N where (1 <= A <= B <= 10?15) and (1 <=N <= 10?9).
Output
For each test case, print the number of integers between A and B inclusive which are relatively prime to N. Follow the output format below.
Sample Input
2 1 10 2 3 15 5Sample Output
Case #1: 5 Case #2: 10Hint
In the first test case, the five integers in range [1,10] which are relatively prime to 2 are {1,3,5,7,9}.? ? ? ?
?題意:
求區間[a,b]中與n互素的數字個數
分析:
考慮一下逆向問題:求1-m之間與n不互素的個數,不互素則一定至少有一個素因子。這樣就可以枚舉n的素因子,然后計算[a,b]區間有多少個n的素因子,其實這并不好算。
考慮[1,a-1]和[1,b]兩個區間與n互素的個數,答案就是二者之差。互素的個數等于總數減去不互素的個數,然后問題轉換為容斥原理經典問題:求1-m中與n互素的數的個數
如果1-m中某個數與n不互素,那么一定可以被n的某個因子整除,所以先枚舉n的所有素因子。
舉個例子,n=12,m=8,12的素因子是2,3,1-8中有幾個是2的倍數呢?num2=8/2=4;? 1-8中有幾個是3的倍數呢?num3=8/3=2,那么1-8之間與12互素的個數是2+4=6個數字嗎?1-8之間與12不互素的是2,3,4,6,8,共5個數字,這是因為同為2和3的倍數的6被計算了兩次,所以要再減去一次num6=8/6,結果是 8/2+8/3-8/(2*3).
結論:如果是奇數個組合,那么符號是加;如果是偶數個組合,那么符號是減;
AC code
#include<bits/stdc++.h> using namespace std; typedef long long ll;vector<ll>p; //返回1-m中與n互素的數的個數 ll fun(ll n,ll m) {p.clear();for(int i=2;i*i<=n;i++){if(n%i==0){p.push_back(i);while(n%i==0) n/=i;}}if(n>1) p.push_back(n);//求n的素因子int num=p.size();//素因子的個數ll s=0;//1到m中與n不互素的數的個數for(ll i=1;i<(1<<num);i++){//從1枚舉到(2^素因子個數)ll cnt=0;ll mul=1;for(ll j=0;j<num;j++){//枚舉每個素因子if(i&(1<<j)){//若對應位置為1,那么計入cnt++;mul*=p[j];}}//容斥原理if(cnt&1) //選取個數為奇數,加s+=m/mul;else //選取個數為偶數,減s-=m/mul;}return m-s;//返回1-m中與n互素的數的個數 }int main() {int T,ca=0;scanf("%d",&T);while(T--){ll n,a,b;scanf("%lld%lld%lld",&a,&b,&n);ll ans=fun(n,b)-fun(n,a-1);printf("Case #%d: %lld\n",++ca,ans);}return 0; }HDU2841
There are many trees forming a m * n grid, the grid starts from (1,1). Farmer Sherlock is standing at (0,0) point. He wonders how many trees he can see.?
If two trees and Sherlock are in one line, Farmer Sherlock can only see the tree nearest to him.
Input
The first line contains one integer t, represents the number of test cases. Then there are multiple test cases. For each test case there is one line containing two integers m and n(1 ≤ m, n ≤ 100000)
Output
For each test case output one line represents the number of trees Farmer Sherlock can see.
Sample Input
2 1 1 2 3Sample Output
1 5?題意:
給一個n*m的矩陣,左下角為(1,1),右上角為(n,m),問從(0,0)點可以看到多少個點。
分析:
如果gcd(x,y)=g,g!=1,那么一定被(x/g,y/g)的點擋住
兩個數字(x,y)如果兩數互質,則可以被看到;如果不互質,則看不到,所以我們就是要找出所有的互質二元組(x,y)
我們可以固定一個數字,用一個數來循環。例如矩陣為n*m,我們固定m,用n來循環,即1與[1,m]里面多少個數互質,2與[1,m]里面多少個數互質,3與[1,m]里面多少個數互質……n與[1,m]里面多少個數互質,把這些結果全部累加起來即可
所以問題的最后變為了,給定一個數字x,找出它和1到y里面有多少個數互質
#include<bits/stdc++.h> using namespace std; typedef long long ll;vector<ll>p; //返回1-m中與n互素的數的個數 ll fun(ll n,ll m) {p.clear();for(int i=2;i*i<=n;i++){if(n%i==0){p.push_back(i);while(n%i==0) n/=i;}}if(n>1) p.push_back(n);//求n的素因子int num=p.size();//素因子的個數ll s=0;//1到m中與n不互素的數的個數for(ll i=1;i<(1<<num);i++){//從1枚舉到(2^素因子個數)ll cnt=0;ll mul=1;for(ll j=0;j<num;j++){//枚舉每個素因子if(i&(1<<j)){//若對應位置為1,那么計入cnt++;mul*=p[j];}}//容斥原理if(cnt&1) //選取個數為奇數,加s+=m/mul;else //選取個數為偶數,減s-=m/mul;}return m-s;//返回1-m中與n互素的數的個數 } int main() {int T,ca=0;scanf("%d",&T);while(T--){ll a,b;scanf("%lld%lld",&a,&b);ll ans=0;for(int i=1;i<=a;i++){ans+=fun(i,b);}printf("%lld\n",ans);}return 0; }HDU1695?
Given 5 integers: a, b, c, d, k, you're to find x in a...b, y in c...d that GCD(x, y) = k. GCD(x, y) means the greatest common divisor of x and y. Since the number of choices may be very large, you're only required to output the total number of different number pairs.?
Please notice that, (x=5, y=7) and (x=7, y=5) are considered to be the same.?
Yoiu can assume that a = c = 1 in all test cases.?
Input
The input consists of several test cases. The first line of the input is the number of the cases. There are no more than 3,000 cases.?
Each case contains five integers: a, b, c, d, k, 0 < a <= b <= 100,000, 0 < c <= d <= 100,000, 0 <= k <= 100,000, as described above.?
Output
For each test case, print the number of choices. Use the format in the example.?
Sample Input
2 1 3 1 5 1 1 11014 1 14409 9Sample Output
Case 1: 9 Case 2: 736427Hint
For the first sample input, all the 9 pairs of numbers are (1, 1), (1, 2), (1, 3), (1, 4), (1, 5), (2, 3), (2, 5), (3, 4), (3, 5).題意:? ,求gcd(x,y)=k的(x,y)的個數
分析:顯然,等價于求b,d同時除以k,求gcd(x,y)=1的個數,因為(1,3)和(3,1)是一種情況,所以要限制(x<y)
#include<bits/stdc++.h> using namespace std; typedef long long ll; vector<ll>p; ll cal(ll n,ll m) {p.clear();for(int i=2;i*i<=n;i++){if(n%i==0){p.push_back(i);while(n%i==0) n/=i;}}if(n>1) p.push_back(n);int num=p.size();ll maxs=1<<num;ll s=0;for(ll i=1;i<maxs;i++){ll cnt=0;ll mul=1;for(ll j=0;j<num;j++){if(i&(1<<j)){cnt++;mul*=p[j];}}if(cnt&1) s+=m/mul;else s-=m/mul;}return m-s; } int main() {int T,ca=0;scanf("%d",&T);while(T--){ll a,b,c,d,k;scanf("%lld%lld%lld%lld%lld",&a,&b,&c,&d,&k);if(!k){printf("Case %d: 0\n",++ca);continue;}b/=k;d/=k;if(b>d) swap(d,b);ll ans=0;for(ll i=1;i<=d;i++){ll k=min(i,b);//求區間[1,k]內與i互質的個數ans+=cal(i,k);}printf("Case %d: %lld\n",++ca,ans);}return 0; }總結
以上是生活随笔為你收集整理的HDU4135 HDU2841 HDU1695 求[1,m]中与n互素的数的个数的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 快速乘法模板
- 下一篇: Catalan Numbers 卡特兰数