类欧几里得

牛客多校第九场

题目链接

类欧几里得 。。。 这谁能想到,看了题解还是感觉联系不是很紧密,题解中的按位来做就是指,我们将二进制的每一位1的个数记录下来。然后算出贡献度就可以了
对于kM&M对于M的每个二进制位考虑就是 ⌊ K M 2 i ⌋ − 2 ∗ ⌊ K M 2 i + 1 ⌋ \lfloor\frac{KM}{2^{i}}\rfloor -2*\lfloor\frac{KM}{2^{i + 1}}\rfloor 2iKM22i+1KM
这两个式子分别用类欧几里得求出,
类欧几里得
代码:

#include
using namespace std;
const int P = 1e9 + 7;
const long long inv2=(P+1)/2;
typedef long long ll;
ll f(ll a,ll b,ll c,ll n){
    if (!a) return 0;
    ll x,y;
    if(a>=c||b>=c){
        x=f(a%c,b%c,c,n);
        y=((a/c)%P*(n%P)%P*((n+1)%P)%P*inv2+b/c%P*((n+1)%P)+x)%P;
        y=(y+P)%P;
        return y;
    }
    ll m=((__int128)a*n+b)/c;
    x=f(c,c-b-1,a,m-1);
    y=((__int128)n*m-x)%P;
    y=(y+P)%P;
    return y;
}
int main(){
    ll n,m;
    cin >> n >> m;
    ll ans = 0;
    for(ll i = 1,j = 0; i <= m; i*= 2, j ++){
        if(m&(1LL << j)){
            ans = (ans + i%P*((f(m, 0 , i, n) - 1LL*2*f(m,0,2*i,n))%P+P)%P)%P;
        }
    }
    ll res = ans%P;
    cout << res << endl;

}

牛客小白月赛18 F
题目链接
对于这类题目做法其实都一样,求出每一位的贡献度加起来,这个题是异或
类欧几里得_第1张图片
知道思路是什么,写的时候还是超了好几发,板子里取模太多

#include 
using namespace std;
typedef long long ll;
const int P = 1e9 + 7;
const long long inv2 =(P+1)/2;

ll f(ll a,ll b,ll c,ll n){
    if (!a) return 0;
    ll x,y;
    if(a>=c||b>=c){
        x=f(a%c,b%c,c,n);
        y=((a/c)*(n)%P*((n+1))%P*inv2+b/c%P*((n+1))+x)%P;
        return y;
    }
    ll m=((__int128)a*n+b)/c;
    x=f(c,c-b-1,a,m-1);
    y=((__int128)n*m-x)%P;
    return y;
}
/*ll f(ll a, ll b, ll c, ll n) {
    if (!a) return b / c * (n + 1) % P;
    if (a >= c || b >= c)
        return (f(a % c, b % c, c, n) + (a / c) * n % P * (n + 1) % P * inv % P + (b / c) * (n + 1) % P) % P;
    ll m = (a * n + b) / c;
    return (n * m - f(c, c - b - 1, a, m - 1)) % P;
}*/
int main()
{
	ll n,m;
    scanf("%lld%lld",&n,&m);
	long long ans = 0;
	for(ll j = 1,x = 0; x <= 34; j *= 2, x ++){
		for(ll i = 0; i <= n; i ++){
			if((m >> x)&1){
				ans = (ans + (n + 1 - (f(i, 0 , j , n) - 2*f(i , 0 ,2*j, n)))*j%P)%P;
			}
			else{
                ans = (ans + (f(i, 0 , j , n) - 2*f(i , 0 ,2*j, n))*j%P)%P;
			}
		}
	}
    if(ans < 0) ans += P;
	printf("%lld\n",ans);
}

你可能感兴趣的:(类欧几里得)