[BZOJ3817]Sum

试题描述

给定正整数N,R。求

输入

第一行一个数 T,表示有 T 组测试数据。

接下来 T 行,每行两个正整数 n,r。

输出

输出 T 行,每行一个整数表示答案。

输入示例

3
3 5
3 6
3 7

输出示例

3
1
-1

数据规模及约定

对于 100% 的数据,满足 n≤10^9,r≤10^4,T≤10^4。

题解

新技能:类欧几里得算法。

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cctype>
#include <algorithm>
#include <cmath>
using namespace std;

const int BufferSize = 1 << 16;
char buffer[BufferSize], *Head, *Tail;
inline char Getchar() {
	if(Head == Tail) {
		int l = fread(buffer, 1, BufferSize, stdin);
		Tail = (Head = buffer) + l;
	}
	return *Head++;
}
int read() {
	int x = 0, f = 1; char c = Getchar();
	while(!isdigit(c)){ if(c == ‘-‘) f = -1; c = Getchar(); }
	while(isdigit(c)){ x = x * 10 + c - ‘0‘; c = Getchar(); }
	return x * f;
}

#define LL long long
int gcd(int a, int b) { return b ? gcd(b, a % b) : a; }
int r;
double x;
int f(int a, int b, int c, int n) {
	if(!n) return 0;
	int t = gcd(gcd(a, b), c); a /= t; b /= t; c /= t;
	int c1 = c - (LL)((b * x + c) / a) * a;
	LL s = (LL)((b * x + c) / a) * ((LL)n * (n + 1) >> 1) + n * (LL)((b * x + c1) / a * n);
	return s - f(b * b * r - c1 * c1, a * b, -a * c1, (b * x + c1) / a * n);
}

int main() {
	int T = read();
	while(T--) {
		int n = read(); r = read();
		x = sqrt(r);
		if(x == (int)x && (r & 1)) printf("%d\n", (n & 1) ? -1 : 0);
		else printf("%d\n", n + (f(2, 1, 0, n) << 2) - (f(1, 1, 0, n) << 1));
	}

	return 0;
}

记得特判 r 是完全平方奇数的情况。(我也不知道为啥。。。)并且记得在函数 f(a, b, c, n) 中要给 a, b, c 约分。

时间: 2024-10-09 03:52:37

[BZOJ3817]Sum的相关文章

BZOJ3817 Sum(类欧几里得算法)

设$t=\sqrt r$,原题转化为$\sum_{x=1}^n(4*\lfloor\frac{tx}2\rfloor-2*\lfloor tx\rfloor)$考虑如何求$\sum_{x=1}^n\lfloor\frac{bt+c}ax\rfloor$开始我写了一个真欧几里得来求直线下整点数目,然后由于里头含小数所以不对.于是学习了一下新姿势,思想其实差不多.先把a,b,c同时除以gcd(a,b,c),防止爆int.之后把斜率变成$\frac{bt+c}a-\lfloor\frac{bt+c}a

bzoj3817 Sum 类欧几里得算法

这道题目solution写了两种做法,都讲一下吧. 首先,令x=r^0.5,显然,如果x>2,则可以不断减2到小于二:如果x>1,那么变为2-x.因此此时必有x<1.(特判r为完全平方数的情况).那么令y=1/x,则: 题目等价于在数轴从0~n,以y长度为一个区间(左闭右开)黑白交替染色,求黑色部分覆盖的整点减去白色部分覆盖的整点.然后把最后面零散的部分暴力计算,如果最后一个是黑色的也暴力计算.那么这个时候黑白段数相等,且每一段黑(白)都至少覆盖[y]个点恰好各自抵消[y],那么将每一段

LeetCode OJ - Sum Root to Leaf Numbers

这道题也很简单,只要把二叉树按照宽度优先的策略遍历一遍,就可以解决问题,采用递归方法越是简单. 下面是AC代码: 1 /** 2 * Sum Root to Leaf Numbers 3 * 采用递归的方法,宽度遍历 4 */ 5 int result=0; 6 public int sumNumbers(TreeNode root){ 7 8 bFSearch(root,0); 9 return result; 10 } 11 private void bFSearch(TreeNode ro

129. Sum Root to Leaf Numbers

Given a binary tree containing digits from 0-9 only, each root-to-leaf path could represent a number. An example is the root-to-leaf path 1->2->3 which represents the number 123. Find the total sum of all root-to-leaf numbers. For example, 1 / 2 3 T

Leetcode 494 Target Sum 动态规划 背包+滚动数据

这是一道水题,作为没有货的水货楼主如是说. 题意:已知一个数组nums {a1,a2,a3,.....,an}(其中0<ai <=1000(1<=k<=n, n<=20))和一个数S c1a1c2a2c3a3......cnan = S, 其中ci(1<=i<=n)可以在加号和减号之中任选. 求有多少种{c1,c2,c3,...,cn}的排列能使上述等式成立. 例如: 输入:nums is [1, 1, 1, 1, 1], S is 3. 输出 : 5符合要求5种

31.SUM() 函数

SUM() 函数 SUM 函数返回数值列的总数(总额). SQL SUM() 语法 SELECT SUM(column_name) FROM table_name SQL SUM() 实例 我们拥有下面这个 "Orders" 表: O_Id OrderDate OrderPrice Customer 1 2008/12/29 1000 Bush 2 2008/11/23 1600 Carter 3 2008/10/05 700 Bush 4 2008/09/28 300 Bush 5

1305 Pairwise Sum and Divide

基准时间限制:1 秒 空间限制:131072 KB 分值: 5 难度:1级算法题 有这样一段程序,fun会对整数数组A进行求值,其中Floor表示向下取整: fun(A) sum = 0 for i = 1 to A.length for j = i+1 to A.length sum = sum + Floor((A[i]+A[j])/(A[i]*A[j])) return sum 给出数组A,由你来计算fun(A)的结果.例如:A = {1, 4, 1},fun(A) = [5/4] + [

Java [Leetcode 303]Range Sum Query - Immutable

题目描述: Given an integer array nums, find the sum of the elements between indices i and j (i ≤ j), inclusive. Example: Given nums = [-2, 0, 3, -5, 2, -1] sumRange(0, 2) -> 1 sumRange(2, 5) -> -1 sumRange(0, 5) -> -3 Note: You may assume that the ar

LeetCode 303. Range Sum Query - Immutable

求数组nums[i,j]的和 思路:另开一sum数组,sum[i]为nums[0,i]的和,所以nums[i,j] = sum[j] - sum[i-1] 1 class NumArray { 2 public: 3 vector<int> sum; 4 NumArray(vector<int> &nums) { 5 sum.resize(nums.size(), 0); 6 sum[0] = nums[0]; 7 int len = nums.size(); 8 for(