UVA 12169 Disgruntled Judge

思路:枚举 a ,通过扩展欧几里得算法利用数列前两个值求 b ,排除非整数解的情况,判断该组 a,b 是否满足剩余序列,(注意必须判断整个序列,不能只判断前几个值,时间够用)。

关于数据范围的第一个问题:b 的范围是 [0,10000] 。由通解公式可知b’=b+10001*t(t 为任意整数),只要通解中的一个解满足序列递推公式,则剩余解都满足。可以简单对其模10001(如第21行,此时 b 的范围是 [-10000,10000]),也可以按照题意中 b 的范围 [0,10000] 令 b=(b%10001+10001)%10001 ,但是必须对 b 进行处理,否则会超出 int/long long 的数据范围。

关于数据范围的第二个问题:强制类型转换long long c=h[2]-(long long)a*a*h[1];  这句运算如果不加 (long long) 会导致出错,这个问题在之前的题中也经常出现,原因是在计算后一项 a*a*h[1] 时,虽然 a、h[1] 都是 int 类型,但是相乘之后的积几乎一定会超出 int 的范围,所以不能在计算乘积之后将得出的 int 类型再转换成 long long 类型,而是应该把 a、h[1] 都转成 long long 类型再进行乘法运算。加上 (long long) 只是显式地将 a 强制转换成 long long 类型 , 不同类型的数据计算时会隐(zi)式(dong)转换成高(chang)类型的数据。

 

 1 #include <cstdio>
 2 using namespace std;
 3 
 4 void exgcd(int a,int b,int & d,int & x,int & y){
 5     if (b==0) {x=1;y=0;d=a;return;}
 6     exgcd(b,a%b,d,y,x);
 7     y-=x*(a/b);
 8 }
 9 
10 int main(){
11     
12     int n,h[10005],a,d,b,l;
13     scanf("%d",&n);
14     for(int i=1;i<=n;i++)
15         scanf("%d",&h[i]);
16 
17     for(a=0;a<10001;a++){
18 
19         exgcd(a+1,10001,d,b,l);
20         long long c=h[2]-(long long)a*a*h[1];
21         b=(b*c/d)%10001;
22         if (c%d) continue;
23         int f=1;
24         for (int i=1;i<n;i++){
25             int temp=(((a*h[i]+b)%10001)*a+b)%10001;
26             if (temp!=h[i+1]){
27                 f=0;
28                 break;
29             }
30         }
31         if (f) {
32             for (int i=1;i<=n;i++)
33                 printf("%d\n",(a*h[i]+b)%10001);
34             return 0;
35         }
36     }
37 }

 

posted @ 2018-03-05 21:44  Travelller  阅读(103)  评论(0编辑  收藏  举报