不妨设a1<a2<a3<a4。显然第一问的答案是4,满足a1+a4=a2+a3,a1+a2|a3+a4,a1+a3|a2+a4。容易发现将其同时扩大k倍是仍然满足条件的,于是考虑gcd(a1,a2,a3,a4)=1的情况。对于a1+a3|a2+a4,由a1+a4=a2+a3,可以发现a2+a4<3(a1+a3),因为2a3>a4且a2<a3,于是也就有a2+a4=2(a1+a3)。然后考虑a1+a2|a3+a4,为保证a2+a4=2(a1+a3),a2和a3大约至多在a1和a4的三等分点取得,于是a2+a4<5(a1+a3)。将a2+a4=4(a1+a3)和a2+a4=3(a1+a3)代入解方程即可,得到的都是和a1的整数倍关系,其中4倍时为1 11 19 29,3倍时为1 5 7 11(样例都很良心的给出来了)。那么合法集合就是这些数的倍数了。勉勉强强推出来了,发现这是个IMO题时非常震惊。
#include<iostream> #include<cstdio> #include<cmath> #include<cstdlib> #include<cstring> #include<algorithm> using namespace std; #define ll long long char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;} int gcd(int n,int m){return m==0?n:gcd(m,n%m);} int read() { int x=0,f=1;char c=getchar(); while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();} while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar(); return x*f; } ll l,r; int main() { #ifndef ONLINE_JUDGE freopen("bzoj4915.in","r",stdin); freopen("bzoj4915.out","w",stdout); const char LL[]="%I64d "; #else const char LL[]="%lld "; #endif cin>>l>>r; cout<<4<<endl<<r/11-min(r/11,l-1)+r/29-min(r/29,l-1); return 0; }