bzoj3817: Sum【类欧几里得算法】

题目大意:

给出T1e4T≤1e4组询问,对于每组询问,给定n1e9,R1e4n≤1e9,R≤1e4,求:

i=1n(1)iR∑i=1n(−1)⌊iR⌋
解题思路:

r=Rr=R,则ir⌊ir⌋为奇数时为-1,为偶数时为1,又有:

x2x2=1,x%2=10,x%2=0⌊x⌋−2⌊x2⌋={1,⌊x⌋%2=10,⌊x⌋%2=0

所以:

ans=i=1n(12(ir2ir2))=n2i=1nir+4i=1nir2ans=∑i=1n(1−2(⌊ir⌋−2⌊ir2⌋))=n−2∑i=1n⌊ir⌋+4∑i=1n⌊ir2⌋

那么如何求形如f(k,n)=i=1nkif(k,n)=∑i=1n⌊ki⌋呢?
还是用类欧几里得的方法:

k1f(k,n)=f(kk,n)+kn(n+1)/2k≥1,f(k,n)=f(k−⌊k⌋,n)+⌊k⌋n(n+1)/2

k<1k<1f(k,n)=i=1nj=1m[kij],m=knf(k,n)=∑i=1n∑j=1m[ki≥j],m=⌊kn⌋
注意这里与普通类欧的不同,这里kk是小数,所以kij并不等价于ki>j1ki>j−1,但当j/kj/k不是整数时等价于i>j/ki>⌊j/k⌋,所以当rr为整数时我们直接计算,只讨论r为无理数的情况:

f(k,n)=i=1nj=1m[i>j/k]f(k,n)=∑i=1n∑j=1m[i>⌊j/k⌋]
f(k,n)=j=1m(nj/k)f(k,n)=∑j=1m(n−⌊j/k⌋)
f(k,n)=nmf(1k,m)f(k,n)=nm−f(1k,m)
一直递归,当n=0n=0时返回0,复杂度据说是O(log)O(log)的,但我并不会证……
(就是n=kn,k=1k1n=kn,k=1k−1一直递归的复杂度)

注意不能斜率不能用double,会卡精,要用k=ar+bck=ar+bc的形式维护整形三元组(a,b,c)(a,b,c)才行,就两个操作,取小数部分和取倒数:

取小数:ar+bck=ar+bkcc,k=ar+bcar+bc−k=ar+b−kcc,k=⌊ar+bc⌋

取倒数:car+b=c(arb)(ar+b)(arb)=acrbca2Rb2car+b=c(ar−b)(ar+b)(ar−b)=acr−bca2R−b2

迭代即可。

#include<bits/stdc++.h>
#define ll long long
using namespace std;
int getint()
{
    int i=0,f=1;char c;
    for(c=getchar();c!='-'&&(c<'0'||c>'9');c=getchar());
    if(c=='-')f=-1,c=getchar();
    for(;c>='0'&&c<='9';c=getchar())i=(i<<3)+(i<<1)+c-'0';
    return i*f;
}
ll n,R;
double r;
ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
ll f(ll a,ll b,ll c,ll n)
{
    if(!n)return 0;
    ll g=gcd(a,gcd(b,c));
    a/=g,b/=g,c/=g;
    ll tmp=(a*r+b)/c; 
    b-=tmp*c,tmp*=n*(n+1)/2;
    ll m=(a*r+b)*n/c;
    return m*n+tmp-f(a*c,-b*c,a*a*R-b*b,m);
}
int main()
{
    //freopen("lx.in","r",stdin);
    for(int T=getint();T;T--)
    {
        n=getint(),R=getint(),r=sqrt(R);
        int x=r;
        if(x*x==R)printf("%d\n",(x&1)?((n&1)?-1:0):n);
        else printf("%d\n",n-2*f(1,0,1,n)+4*f(1,0,2,n));
    }
    return 0;
}
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值