zoukankan      html  css  js  c++  java
  • [atARC111E]Simple Math 3

    首先,必然要有$(a+ci)-(a+bi)+1<d$,因此$(c-b)ile d-2$,即$ile lfloorfrac{d-2}{c-b} floor$

    此时,$[a+bi,a+ci]$中不存在$d$的倍数,当且仅当$lfloorfrac{a+bi-1}{d} floor=lfloorfrac{c+bi}{d} floor$,同时两者之差不大于2,因此可以通过求和来统计,即$n-sum_{i=1}^{n}lfloorfrac{a+ci}{d} floor-lfloorfrac{a+bi-1}{d} floor$(其中$n=lfloorfrac{d-2}{c-b} floor$)

    这两个式子是类似的,因此可以仅考虑$sum_{i=1}^{n}lfloorfrac{a+ci}{d} floor$

    将后者用1累加的形式来表示,即$sum_{i=1}^{n}sum_{1le jle lfloorfrac{a+ci}{d} floor}1$

    调换枚举顺序,令$n'=lfloorfrac{a+cn}{d} floor$,因此即$sum_{j=1}^{n'}sum_{1le ile n,jle lfloorfrac{a+ci}{d} floor}1$

    考虑$jle lfloorfrac{a+ci}{d} floor$,改为用$j$来限制$i$,即$lceilfrac{jd-a}{c} ceil=lfloorfrac{jd-a+c-1}{c} floorle ile n$

    同时注意到$a<d$且$jge 1$,即保证了$lfloorfrac{jd-a+c-1}{c} floorge 1$

    再将后者1的累加展开,即$sum_{j=1}^{n'}n-lfloorfrac{jd-a+c-1}{c} floor+1=n'(n+1)-sum_{j=1}^{n'}lfloorfrac{(c-a-1)+jd}{c} floor$

    因此,即记$f(n,a,c,d)=sum_{i=1}^{n}max(lfloorfrac{a+ci}{d} floor,0)$,则$f(n,a,c,d)=n'(n+1)-f(n',c-a-1,d,c)$

    另外,$f(n,a,c,d)$还有以下变换来规范其形式,即:

    1.若$age d$,$f(n,a,c,d)=f(n,a mod d,c,d)+lfloorfrac{a}{d} floor n$

    2.若$a<0$,$f(n,a,c,d)=f(n,a+kd,c,d)-kn$(其中$k=lfloorfrac{-a+d-1}{d} floor$)

    3.若$cge d$,$f(n,a,c,d)=f(n,a,c mod d,d)+lfloorfrac{c}{d} floor{n+1choose 2}$

    4.若$c=0$,$f(n,a,c,d)=0$

    注意到其关于$(c,d)$的变换形式与扩展欧几里得相同,因此复杂度为$o(log_{2}d)

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define ll long long
     4 int t,a,b,c,d;
     5 ll n;#include<bits/stdc++.h>
     6 using namespace std;
     7 #define ll long long
     8 int t,a,b,c,d;
     9 ll n;
    10 ll f(ll n,int a,int c,int d){
    11     if (a>=d)return f(n,a%d,c,d)+(a/d)*n;
    12     if (a<0){
    13         int k=(-a+d-1)/d;
    14         return f(n,a+k*d,c,d)-k*n;
    15     }
    16     if (c>=d)return f(n,a,c%d,d)+(n+1)*n/2*(c/d);
    17     if (!c)return 0;
    18     ll nn=(a+c*n)/d;
    19     return nn*(n+1)-f(nn,c-a-1,d,c);
    20 }
    21 int main(){
    22     scanf("%d",&t);
    23     while (t--){
    24         scanf("%d%d%d%d",&a,&b,&c,&d);
    25         n=(d-2)/(c-b);
    26         printf("%lld
    ",n-f(n,a,c,d)+f(n,a-1,b,d));
    27     }
    28 } 
    29 ll f(ll n,int a,int c,int d){
    30     if (a>=d)return f(n,a%d,c,d)+(a/d)*n;
    31     if (a<0){
    32         int k=(-a+d-1)/d;
    33         return f(n,a+k*d,c,d)-k*n;
    34     }
    35     if (c>=d)return f(n,a,c%d,d)+(n+1)*n/2*(c/d);
    36     if (!c)return 0;
    37     ll nn=(a+c*n)/d;
    38     return nn*(n+1)-f(nn,c-a-1,d,c);
    39 }
    40 int main(){
    41     scanf("%d",&t);
    42     while (t--){
    43         scanf("%d%d%d%d",&a,&b,&c,&d);
    44         n=(d-2)/(c-b);
    45         printf("%lld
    ",n-f(n,a,c,d)+f(n,a-1,b,d));
    46     }
    47 } 
    View Code
  • 相关阅读:
    Spring sprint @ ninth day
    微软面试:找水王问题
    Spring sprint @ first day
    软件工程概论 购书最低价格问题
    网络助手的NABCD分析
    记初学net-SNMP
    求二维数组联通子数组和的最大值 (联通涂色) beta!
    二维数组环状最大子矩阵
    一维数组中的最大子数组(环状)
    图书助手冲刺第七天
  • 原文地址:https://www.cnblogs.com/PYWBKTDA/p/14307667.html
Copyright © 2011-2022 走看看