[USACO24JAN] Cowlendar S
题面
原题链接
简介:给出 \(a_1....a_n\),对所有满足 s 的 \(L\) 求和
s 为:
- \(\forall i,4 \times L \leq a_i\)
- \(a_i \bmod L\) 不超过 \(3\) 种不同的值。
\(1 \leq a_i \leq 4 \cdot 10^9\)
题解
一种暴力的做法是枚举 \(L\) ,然后 \(O(n)\) 检查是否合法,在这题的数据范围下显然难以通过。考虑发掘性质降低枚举量。
余数最多有三种,这个必要条件很强,我们考虑从它入手。根据鸽巢原理,对于所有合法的 \(L\) ,前 \(4\) 个 \(a\) 在模 \(L\) 的意义下必然有两个同余,否则与这个必要条件相悖。同时对于两个模 \(L\) 同余的 \(a_i,a_j\),有 \(L \mid a_j-a_i\) 。我们考虑暴力配对前四个 \(a\) 作差,就能获得所有合法的 \(L\) 的倍数,对这些倍数枚举因子即可,最后再 \(O(n)\) 检查保证条件充要。
\(10^9\) 级别的数的因子个数最大只有 \(1000\) 左右,所以这样枚举大大降低了我们对 \(L\) 的枚举量,做题时留心观察题目限制,抓中某些很强的限制,往往都能引导正解。
const int N=1e5+5;
const int inf=1e18;
int n,a[N],mn=inf,len;
set<int> s;
bool chk(int x){set<int> num;for(int i=1;i<=len;i++){num.insert(a[i]%x);if(num.size()>3) return false;}return true;
}
void xpigeon(){cin>>n;for(int i=1;i<=n;i++){cin>>a[i];mn=min(mn,a[i]);}sort(a+1,a+n+1);len=unique(a+1,a+n+1)-(a+1);if(len<=3){cout<<(mn/4)*(mn/4+1)/2<<'\n';return ;}for(int i=1;i<=4;i++){for(int j=i+1;j<=4;j++){int num=abs(a[j]-a[i]);for(int k=1;k*k<=num;k++){if(num%k!=0) continue;if(k*4>mn) break;if(chk(k)) s.insert(k);if((num/k)*4<=mn && chk(num/k)) s.insert(num/k);}}}int ans=0;for(auto i:s) ans+=i;cout<<ans<<'\n';
}