形如a*x+b*y=c
为不定方程,a,b>0其实无所谓,因为gcd(a,b)=gcd(|a|,|b|) //gcd为最大公约数
由数论的定理所知,当c%gcd==0,不定方程有解,现在我们来求这个解.
gcd=gcd(a,b);a*b=gcd*lcm; //lcm为最小公倍数
a‘=a/gcd;b‘=b/gcd;c‘=c/gcd; a‘目前与b‘互质
令c‘‘=1=a‘*x+b‘*y;
利用extend_gcd求出一组特解。(x0,y0)
(x0*c‘.y0*c‘)为 a‘*x+b‘*y=c‘的一组特解
由方程解的思想求出其通解;x=x0*c‘+b‘*t; y=y0*c‘-a‘*t;再用通解去求解题目
今天花了一晚上时间纠结了一个显而易见的问题。果然当局者迷。
我现在就想大笑一场。哈哈哈哈哈哈哈哈
题目意思:t个case,n个野人,C,P,L分别代表初始洞穴,隔天移动洞穴数,存活天数。
问:最小的洞穴数,使得在n个野人在各自存活期不遇见。
数据:1*10^6 可以接受,所以此题以初值为野人中初始洞穴最大数,枚举就可以过了。
源代码:
1 #include <iostream> 2 #include <algorithm> 3 #include <cstdio> 4 5 using namespace std; 6 7 int x,y,gcd,n; 8 int C[20],P[20],L[20]; 9 10 void extend_gcd(int a,int b) 11 { 12 if(b==0) 13 { 14 x=1; 15 y=0; 16 gcd=a; 17 return; 18 } 19 extend_gcd(b,a%b); 20 int tmp=x; 21 x=y; 22 y=tmp-a/b*y; 23 return; 24 } 25 26 bool solve(int i,int j,int m) 27 { 28 int c=C[i]-C[j]; 29 int b=m; 30 int a=P[j]-P[i]; 31 extend_gcd(a,b); 32 if(c%gcd) return false; 33 x*=c/gcd; 34 if(gcd<0) gcd=-gcd; 35 //因为x=x+b/gcd*k,所以x中包含了若干个b/gcd的代数和差 36 //因此用x对b/gcd取模,注意负数得x的最小正值 37 x=(x%(b/gcd)+b/gcd)%(b/gcd); 38 if(x<=L[i] && x<=L[j]) 39 return true; 40 return false; 41 } 42 bool test(int m) 43 { 44 for(int i=0;i<n-1;i++) 45 for(int j=i+1;j<n;j++) 46 { 47 if(solve(i,j,m)) return false; 48 } 49 return true; 50 } 51 52 53 int main() 54 { 55 int t; 56 scanf("%d",&t); 57 while(t--) 58 { 59 scanf("%d",&n); 60 int lb=0; 61 for(int i=0;i<n;i++) 62 { 63 scanf("%d %d %d",C+i,P+i,L+i); 64 lb=max(lb,C[i]); 65 C[i]--; 66 } 67 while(lb<=1000000) 68 { 69 if(test(lb)) break; 70 lb++; 71 } 72 printf("%d\n",lb); 73 } 74 return 0; 75 } 76 //提供测试数据 77 Sample Input 78 2 79 3 80 1 3 4 81 2 7 3 82 3 2 1 83 5 84 1 2 14 85 4 4 6 86 8 5 9 87 11 8 13 88 16 9 10 89 Sample Output 90 6 91 33
时间: 2024-11-09 13:06:40