HackerRank - mehta-and-the-typical-supermarket
Mehta is a very rich guy. He has types of coins, and each type of coin is available in an unlimited supply.
So Mehta goes to a supermarket to buy monthly groceries. There he sees that every item has a unique price, that is, no two items have the same price.
Now, the supermarket owner tells Mehta that they are selling items in the price range only on that particular day. He also tells Mehta that for every price, there is an item in the shop.
The supermarket has recently adopted a weird new tradition: Mehta may only use a single type of coin for each item he purchases. For example, he could pay for an item of price 4 with two 2-coins, but not with a 3-coin and a 1-coin.
As you know Mehta is very weak at calculations, so he wants you to do these calculations for him and tell how many different types of items he can buy.
Input Format
The first line of input contains , the number of types of coins Mehta has.
Then the next lines contain an integer each: the ith line contains , the value of Mehta’s ith type of coin.
Then the next line contains a number , the number of days Mehta goes shopping.
Then each of the next lines contains numbers and , denoting that they are selling items in price range on that particular day.
Output format
There will be lines, each containing the number of distinct items that can be bought at that particular day.
Constraints
Sample Input
4
2
3
4
5
3
1 10
2 20
3 7
Sample output
8
14
4
Explanation
For and you can buy items of price .
For and you can buy items of price .
For and you can buy items of price .
题意:给出n个数A[i],然后有D个询问,包括L,R,然后求出【L,R】其中能被A[i]整除的数的数目。
分析:用F(a1,a2,…,an)表示在【L,R】期间能被a1,a2,…,an整除的数目,即答案。
然后根据容斥原来得
F(a1,a2,…,an)=∑F(ai)-∑F(ai,aj)+∑F(ai,aj,ak)-∑F(ai,aj,ak,al)…
而F(a1,a2,…,an)=F(lcm(a1,a2,…an);
且F(a)=R/a-(L-1)/a;
此题中的lcm有可能会出现爆long long ,所以得特断一下
然后得预处理一下, 不然会超时
#include<iostream>
#include<string>
#include<cstdio>
#include<cstring>
#include<vector>
#include<math.h>
#include<map>
#include<queue>
#include<algorithm>
using namespace std;
const int inf = 0x3f3f3f3f;
typedef pair<int,int> pii;
typedef pair<long long ,long long> pll;
const long long INF = 2000000000000000000;
pll p[1<<18];
int n,d;
long long a[50];
long long L,R;
long long real(long long a,long long b){//a*b有可能爆longlong
return (INF/a>=b?a*b:INF);
}
long long gcd (long long a,long long b){//最大公约数
if (b==0)return a;
return gcd(b,a%b);
}
void init(int n){//预处理,先求出对应的最小公倍数以及cnt
long long lcm;
int cnt=0;
for (int i=1;i<(1<<n);i++){
lcm=1;
cnt=0;
for (int j=0;j<n;j++){
if (i&(1<<j)){
cnt++;
lcm=real(lcm/gcd(lcm,a[j]),a[j]);
}
}
p[i].first=lcm;
p[i].second=cnt;
}
}
int main ()
{
scanf ("%d",&n);
for (int i=0;i<n;i++){
scanf("%lld",&a[i]);
}
init(n);//预处理
scanf ("%d",&d);
while (d--){
scanf ("%lld%lld",&L,&R);
long long ans=0;
for (int i=1;i<(1<<n);i++){
long long tmp= (R/p[i].first-(L-1)/(p[i].first));
if (p[i].second%2){
ans+=tmp;
}else ans-=tmp;
}
printf ("%lld\n",ans);
}
return 0;
}