BZOJ 1257 [CQOI2007]余数之和sum ——Dirichlet积

【题目分析】

卷积很好玩啊。

【代码】

#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>

#include <map>
#include <set>
#include <queue>
#include <string>
#include <iostream>
#include <algorithm>

using namespace std;

#define maxn 500005
#define ll long long
#define inf 0x3f3f3f3f
#define F(i,j,k) for (int i=j;i<=k;++i)
#define D(i,j,k) for (int i=j;i>=k;--i)

void Finout()
{
    #ifndef ONLINE_JUDGE
    freopen("in.txt","r",stdin);
    freopen("wa.txt","w",stdout);
    #endif
}

int Getint()
{
    int x=0,f=1; char ch=getchar();
    while (ch<‘0‘||ch>‘9‘) {if (ch==‘-‘) f=-1; ch=getchar();}
    while (ch>=‘0‘&&ch<=‘9‘) {x=x*10+ch-‘0‘; ch=getchar();}
    return x*f;
}

int n,k,r,l;
ll ans=0;

int main()
{
    Finout();
    n=Getint(); k=Getint();
    ans=(ll)n*(ll)k;
//    cout<<"ans  is "<<ans<<endl;
	int now=1; r=min(n,k);
    while (r)
    {
    	now=k/r;
//    	cout<<now<<" "<<n<<" "<<k<<" "<<r<<endl;
    	l=k/(now+1)+1;
//    	cout<<"now "<<now<<endl;
//    	cout<<l<<"---"<<r<<endl;
    	ans-=((ll)r+(ll)l)*((ll)r-(ll)l+1)/2LL*(ll)now;
//    	cout<<"ans is "<<ans<<endl;
    	r=l-1;
//    	cout<<"r is "<<r<<endl;
	}
	cout<<ans<<endl;
}

  

时间: 2024-10-17 00:28:16

BZOJ 1257 [CQOI2007]余数之和sum ——Dirichlet积的相关文章

BZOJ 1257: [CQOI2007]余数之和sum【神奇的做法,思维题】

1257: [CQOI2007]余数之和sum Time Limit: 5 Sec  Memory Limit: 162 MBSubmit: 4474  Solved: 2083[Submit][Status][Discuss] Description 给出正整数n和k,计算j(n, k)=k mod 1 + k mod 2 + k mod 3 + … + k mod n的值,其中k mod i表示k除以i的余数.例如j(5, 3)=3 mod 1 + 3 mod 2 + 3 mod 3 + 3

bzoj 1257: [CQOI2007]余数之和sum 数学 &amp;&amp; 枚举

1257: [CQOI2007]余数之和sum Time Limit: 5 Sec  Memory Limit: 162 MBSubmit: 1779  Solved: 823[Submit][Status] Description 给出正整数n和k,计算j(n, k)=k mod 1 + k mod 2 + k mod 3 + … + k mod n的值,其中k mod i表示k除以i的余数.例如j(5, 3)=3 mod 1 + 3 mod 2 + 3 mod 3 + 3 mod 4 + 3

BZOJ 1257: [CQOI2007]余数之和sum( 数论 )

n >= k 部分对答案的贡献为 k * (n - k) n < k 部分贡献为 ∑ (k - ⌊k / i⌋ * i)  = ∑  , ⌊k / i⌋ 相等的数是连续的一段, 此时这段连续的数对答案的贡献成等差数列, 可以O(1)求出..然后就分⌊k / i⌋ 相等的一块一块来就行了. 分出来大概是sqrt(k)块.这个sqrt(k)我并不会证Orz...写了个程序验证了一下, 分出来的块数和2 * sqrt(k)非常接近. 所以时间复杂度为O(sqrt(k)) --------------

[BZOJ 1257] [CQOI2007] 余数之和sum 【数学】

题目链接:BZOJ - 1257 题目分析 首先, a % b = a - (a/b) * b,那么答案就是 sigma(k % i) = n * k - sigma(k / i) * i     (1 <= i <= n) 前面的 n * k 很容易算,那么后面的 sigma(k / i) * i,怎么办呢? 我们可以分情况讨论,就有一个 O(sqrtk) 的做法. 1)当 i < sqrtk 时,直接枚举算这一部分. 2)当 i >= sqrtk 时, k / i <=

BZOJ 1257 [CQOI2007]余数之和sum(计数优化)

[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=1257 [题目大意] 给出正整数n和k,计算j(n,k)=k mod 1 + k mod 2 + k mod 3 + … + k mod n的值 [题解] 我们发现k%i=k-[k/i]*i,j(n,k)=n*k-∑[k/i]*i,我们知道[k/i]的取值不超过k^(1/2)个, 并且在分布上是连续的,所以我们可以分段求和,对于段开头l,其段结尾r=k/[k/l]. [代码] #inc

bzoj 1257: [CQOI2007]余数之和sum

这是个神题233(一开始想的也差不多,然而不知道为什么觉得复杂度不对,(没想到等差数列,就GG掉了)) 一个数k,k/x=y...?,?构成等差数列,直接o(1)解决,每得出一个y的区间,是[i,last](last见程序,至于为什么,写写看看,挺显然的) 1 #include<bits/stdc++.h> 2 #define N 100005 3 #define LL long long 4 #define inf 0x3f3f3f3f 5 #define ls tr[x][0] 6 #de

1257: [CQOI2007]余数之和sum

1257: [CQOI2007]余数之和sum Time Limit: 5 Sec  Memory Limit: 162 MBSubmit: 2001  Solved: 928[Submit][Status] Description 给出正整数n和k,计算j(n, k)=k mod 1 + k mod 2 + k mod 3 + … + k mod n的值,其中k mod i表示k除以i的余数.例如j(5, 3)=3 mod 1 + 3 mod 2 + 3 mod 3 + 3 mod 4 + 3

[原博客] BZOJ 1257 [CQOI2007] 余数之和

题目链接题意: 给定n,k,求 ∑(k mod i) {1<=i<=n} 其中 n,k<=10^9. 即 k mod 1 + k mod 2 + k mod 3 + … + k mod n的值. 我们先来看商之和. 给定n,k,求∑(k/i) {1<=i<=n} 其中/为整除. 可以得到一个引理,k/i值的个数不超过2*√k种.证明:k整除小于√k的数,都会有一个不同的结果:k整除大于√k的数,结果肯定小于√k,所以最多也只能有√k种结果. 于是我们可以枚举结果的取值累加.是

bzoj 1257 : [CQOI2007]余数之和 (数学+分块)

Description 给出正整数n和k,计算j(n, k)=k mod 1 + k mod 2 + k mod 3 + … + k mod n的值 其中k mod i表示k除以i的余数. 例如j(5, 3)=3 mod 1 + 3 mod 2 + 3 mod 3 + 3 mod 4 + 3 mod 5=0+1+0+3+3=7 Input 输入仅一行,包含两个整数n, k. 1<=n ,k<=10^9 Output 输出仅一行,即j(n, k). Sample Input 5 3 Sample