好像每次洛谷月赛T1都是所谓的签到题,然而并不是很简单。开场我暴力打表找规律,75分钟1A。这是官方题解,然而zzq神犇不会(不屑于)证明,我证一下。
首先,对于满足
(a,b)=1
的二元组
a,b
设
m=a+b
,则无论是
a,b
变成
2a,b−a
还是
a−b,2b
,都相当于模m意义下,
a,b
变成
2a,2b
然后,设k次操作后变成
(2ka,2kb)
,且
2ka≡2kb(modm)
,则
2k(a−b)≡0(modm)
因为
(a,b)=1
,所以
(a,a+b)=1
,即
(a,m)=1
因为
a≡b(modm)
,所以代入
2k(a−b)≡0(modm)
得
2k∗2a≡0(modm)
因为
a≠0
,所以
2k∗2≡0(modm)
,所以m必为2的幂次。
lyx大佬说这个结论是显然的,我却还要写下来,果然是我太渣了。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<string>
#include<queue>
#include<set>
#include<map>
#include<vector>
#include<list>
#include<fstream>
#include<cmath>
#include<cctype>
#include<stack>
#include<cstdlib>
#include<ctime>
using namespace std;
typedef long long ll;
typedef unsigned int ui;
ll n,i,j,d,ans,k;
int main(){
//freopen("aa1.txt","r",stdin);
cin>>n;
for(d=2;;d<<=1){
for(i=(d>>1)+1;i<d && i<=n;){
j=n/(n/i);
if(j>d)j=d-1;
if(j>n)j=n;
if(!(j&1))--j;
ans+=k*(n/i)*(((j-i)>>1)+1);
i=j+2;
}
//cout<<ans<<endl;
++k;
if(d>=n)break;
}
cout<<ans*2;
return 0;
}