我正在尝试解决在线法官问题: http: //opc.iarcs.org.in/index.php/problems/LEAFEAT
简而言之,问题是:
如果给定一个整数 L 和一组 N 个整数 s1,s2,s3..sN,我们必须找出从 0 到 L-1 有多少个数不能被任何 'si' 整除。
例如,如果给定我们, L = 20
那么S = {3,2,5}
从 0 到 19 有 6 个数字不能被 3,2 或 5 整除。
L <= 1000000000 和 N <= 20。
我使用了包含-排除原则来解决这个问题:
/*Let 'T' be the number of integers that are divisible by any of the 'si's in the
given range*/
for i in range 1 to N
for all subsets A of length i
if i is odd then:
T += 1 + (L-1)/lcm(all the elements of A)
else
T -= 1 + (L-1)/lcm(all the elements of A)
return T
这是我解决这个问题的代码
#include <stdio.h>
int N;
long long int L;
int C[30];
typedef struct{int i, key;}subset_e;
subset_e A[30];
int k;
int gcd(a,b){
int t;
while(b != 0){
t = a%b;
a = b;
b = t;
}
return a;
}
long long int lcm(int a, int b){
return (a*b)/gcd(a,b);
}
long long int getlcm(int n){
if(n == 1){
return A[0].key;
}
int i;
long long int rlcm = lcm(A[0].key,A[1].key);
for(i = 2;i < n; i++){
rlcm = lcm(rlcm,A[i].key);
}
return rlcm;
}
int next_subset(int n){
if(k == n-1 && A[k].i == N-1){
if(k == 0){
return 0;
}
k--;
}
while(k < n-1 && A[k].i == A[k+1].i-1){
if(k <= 0){
return 0;
}
k--;
}
A[k].key = C[A[k].i+1];
A[k].i++;
return 1;
}
int main(){
int i,j,add;
long long int sum = 0,g,temp;
scanf("%lld%d",&L,&N);
for(i = 0;i < N; i++){
scanf("%d",&C[i]);
}
for(i = 1; i <= N; i++){
add = i%2;
for(j = 0;j < i; j++){
A[j].key = C[j];
A[j].i = j;
}
temp = getlcm(i);
g = 1 + (L-1)/temp;
if(add){
sum += g;
} else {
sum -= g;
}
k = i-1;
while(next_subset(i)){
temp = getlcm(i);
g = 1 + (L-1)/temp;
if(add){
sum += g;
} else {
sum -= g;
}
}
}
printf("%lld",L-sum);
return 0;
}
next_subset(n)
生成数组中大小为 n 的下一个子集,A
如果没有子集,则返回 0,否则返回 1。它基于此stackoverflow 问题中接受的答案所描述的算法。
该lcm(a,b)
函数返回 a 和 b 的 lcm。该get_lcm(n)
函数返回 中所有元素的 lcm A
。它使用属性:LCM(a,b,c) = LCM(LCM(a,b),c)
当我将问题提交给法官时,它会给我一个“超出时间限制”。如果我们使用蛮力解决这个问题,我们只能得到 50% 的分数。
由于最多可以有 2^20 个子集,我的算法可能会很慢,因此我需要一个更好的算法来解决这个问题。
编辑:
在编辑我的代码并将函数更改为欧几里得算法后,我得到了错误的答案,但我的代码在时间限制内运行。它给了我对示例测试的正确答案,但对任何其他测试用例都没有;这是我运行代码的ideone的链接,第一个输出是正确的,但第二个不是。
我解决这个问题的方法正确吗?如果是,那么我在代码中犯了一个错误,我会找到它;否则谁能解释什么是错的?