HDU 5768 Lucky7
题目:Lucky7
链接:http://acm.hdu.edu.cn/showproblem.php?pid=5768
题意:给你两个数组a[],b[],当某一个数x能整除7,且对所有的i,x%a[i]!=b[i],则称这个数是幸运数,问区间l、r中有多少幸运数。
思路:
线性同余(中国剩余定理可解)+容斥。
坑点:使用中国剩余定理的计算过程中,有可能会爆longlong,需要自己写个快速乘取余。比赛的时候脑袋有点晕,wa到死就是没看到这点,好坑。
大概思路就是找出区间内所有7的倍数,减去那些取余a[i]会等于b[i]的情况。 基本上就是模板题了,没什么好讲的。
AC代码:
1 #include<stdio.h> 2 typedef long long LL; 3 void exGcd(LL a,LL b,LL &d,LL &x,LL &y) 4 { 5 if(b==0) 6 { 7 d=a; 8 x=1; 9 y=0; 10 } 11 else 12 { 13 exGcd(b,a%b,d,x,y); 14 LL t=x; 15 x=y; 16 y=t-a/b*y; 17 } 18 } 19 20 LL mul(LL a,LL b,LL mod) 21 { 22 LL ret=0; 23 while(b) 24 { 25 if(b&1) ret=(ret+a)%mod; 26 a=(a+a)%mod; 27 b>>=1; 28 } 29 return ret; 30 } 31 32 LL fun1(LL aa,LL bb,LL &pp) 33 { 34 LL m=aa*7; 35 LL a[2],b[2]; 36 a[0]=aa; 37 b[0]=bb; 38 a[1]=7; 39 b[1]=0; 40 41 pp=0; 42 for(LL i=0;i<2;i++) 43 { 44 LL mi=m/a[i],d,p,q; 45 exGcd(mi,a[i],d,p,q); 46 p=(p%a[i]+a[i])%a[i]; 47 pp=(pp+mul(mul(mi,p,m),b[i],m))%m; 48 } 49 pp%=m; 50 return m; 51 } 52 LL a[20],b[20]; 53 LL fun(LL *st,LL so,LL &pp) 54 { 55 LL m=1; 56 for(LL i=0;i<so;i++) 57 { 58 m*=a[st[i]]; 59 } 60 pp=0; 61 for(LL i=0;i<so;i++) 62 { 63 LL mi=m/a[st[i]],d,p,q; 64 exGcd(mi,a[st[i]],d,p,q); 65 p=(p%a[st[i]]+a[st[i]])%a[st[i]]; 66 pp=(pp+mul(mul(mi,p,m),b[st[i]],m))%m; 67 } 68 pp%=m; 69 return m; 70 } 71 LL l,r; 72 LL n; 73 LL fin(LL a,LL b,LL l,LL r) 74 { 75 l-=b; 76 r-=b; 77 l+=a; 78 r+=a; 79 return r/a-(l-1)/a; 80 81 } 82 void dfs(LL num,LL ceng,LL j,LL *st,LL so,LL &all) 83 { 84 if(ceng==num) 85 { 86 LL p; 87 LL m=fun(st,so,p); 88 LL pp; 89 LL mm=fun1(m,p,pp); 90 91 92 LL tmp=fin(mm,pp,l,r); 93 94 all+=tmp; 95 //printf("pp=%I64d mm=%I64d all=%I64d\n",pp,mm,all); 96 return ; 97 } 98 for(LL i=j;i<n;i++) 99 { 100 st[so++]=i; 101 dfs(num,ceng+1,i+1,st,so,all); 102 so--; 103 } 104 } 105 LL st[1000],so; 106 int main() 107 { 108 LL t,cas=1; 109 scanf("%I64d",&t); 110 while(t--) 111 { 112 scanf("%I64d%I64d%I64d",&n,&l,&r); 113 for(LL i=0;i<n;i++) 114 { 115 scanf("%I64d%I64d",&a[i],&b[i]); 116 } 117 LL sum=0; 118 for(LL i=1;i<=n;i++) 119 { 120 so=0; 121 LL all=0; 122 //printf("==========%d\n",i); 123 dfs(i,0,0,st,so,all); 124 if(i%2==1) 125 { 126 sum+=all; 127 } 128 else sum-=all; 129 } 130 printf("Case #%I64d: %I64d\n",cas++,r/7-(l-1)/7-sum); 131 } 132 return 0; 133 }