2887: 分糖果
题目描述
sjjj、jljj和ylgg成功夺得首块CCPC银牌,这是个值得纪念的时刻。sjjj很开心,决定给ACM的队员们分些糖果吃(据说吃了sjjj的糖可以拿牌子)。
已知sjjj手里有无数块糖果(有钱任性),队里有 m 个人,sjjj不想简简单单的分糖果,于是想了个法子,他决定将一些糖果放到一个 n 行 n 列二维矩阵中,第 i 行,第 j 列的区域内就放 i^2 + j^2 个糖果。
sjjj想让你告诉他 n * n 个区域有多少个区域内的糖果可以恰好平均分给 m 个队员。(sjjj当然知道结果,他就是想单纯的为难你)
输入
输入一行包含两个整数 n(1 <= n <= 109),m(1 <= m <= 103) 。
输出
输出一个整数,糖果可以恰好平均分给 m 个队员的区域数量。
样例输入 Copy
6 5
样例输出 Copy
13
提示
如下区域内的糖果可以恰好平均分给队员
-
(1,2)和(2,1),1^2 + 2^2=5,恰好可以平均分给5个队员;
-
(1,3)和(3,1);
-
(2,4)和(4,2);
-
(2,6)和(6,2);
-
(3,4)和(4,3);
-
(3,6)和(6,3);
-
(5,5);
解析:由题意得
可推理:
通过推理得出的公式可得:只需要找出0~m-1的余数进行判断即可,这里用cnt[]数组来存储其余数的个数,然后只需要判断余数平方相加是否对m取余为零,若是则表明该组合可以,那么直接将他们的组合个数求出来即可,即
注:因为两个数相乘可能会爆int,所以需要转化一下,否则可能出现测试样例不通过的情况。
import java.util.Scanner;
public class Main{
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner cin=new Scanner(System.in);
int n=cin.nextInt();
int m=cin.nextInt();
long ans=0;
int cnt[]=new int[m];
//得到n中有多少个0~m-1
for(int i=0;i<m;i++)cnt[i]=n/m;
//将n~n-n%m之间的数枚举一下,因为上一个循环只是枚举1~i(i为1~n中%m==0最大的数);
for(int i=n;i>n-n%m;i--) {
cnt[i%m]++;
}
for(int i=0;i<m;i++) {
for(int j=0;j<m;j++) {
if((i*i+j*j)%m==0) {
//组合得到有多少种答案;
ans+=(long)cnt[i]*cnt[j];
}
}
}
System.out.println(ans);
}
}
2889: 移动元素
题目描述
OH哥哥最近迷上了移动元素,通过移动元素来找规律。这天,他发现对于一个给定的数组,选择其中任意一个元素,并将其移动到数组中任意一个位置(也可以保持不动),便有可能将该数组分为前后两个非空部分,并使前一部分的各元素之和等于后一部分的各元素之和(此操作只允许进行一次)。
那么,如果给你一些数组,你能能帮助OH哥哥找出哪些数组可以达成吗?
输入
第一行包含整数 T(1 <= T <= 20),表示共有 T 组测试数据。
每组数据第一行包含整数 n(1 <= n <= 105) 。
第二行包含 n 个整数a1,a2,...an (1 <= ai <= 109)。
输出
每组数据输出一行结果,如果可以达成输出YES,否则输出NO。
样例输入 Copy
3 3 1 3 2 5 1 2 3 4 5 5 2 2 3 4 5
样例输出 Copy
YES NO YES
解析:因为分割,只有偶数才能进行分割,移动元素可以从左往右移动,也可以从后往前移动,只需要判断 前缀和 和 后缀和 是否成立即可,通过为判断条件,看a[1]-a[i]中是否存在这个数,而判断我们就可以使用set
#include<bits/stdc++.h>
#define IOS ios::sync_with_stdio(false)
using namespace std;
const int N=100010;
//a[]数组用来存储正序的数,b[]数组用存储逆序的数,便于后续得到前缀和,后缀和
int a[N],b[N];
typedef long long LL;
LL p[N];
int n;
bool check(int *arr){
for(int i=1;i<=n;i++){
//得到该数组的前缀和
p[i]=p[i-1]+arr[i];
}
//使用集合判断是否符合条件
set<LL> s;
s.insert(0);
for(int i=1;i<=n;i++){
//每次循环判断的是0-i之间是否有符合的数
s.insert(arr[i]);
if(s.count(p[i]-p[n]/2))return true;
}
return false;
}
int main(){
IOS; cin.tie(0);
int t;
cin>>t;
while(t-->0){
cin>>n;
for(int i=1,j=n;i<=n&&j>=1;i++,j--){
cin>>a[i];
b[j]=a[i];
p[i]=p[i-1]+a[i];
}
//保证数组之和是偶数才能进行分割判断;
if(p[n]%2!=0)printf("NO\n");
else{
//如果前缀和和后缀和有一个满足条件 ,即可以进行分割
if(check(a)||check(b))printf("YES\n");
else printf("NO\n");
}
}
return 0;
}
2890: 数字反转
题目描述
大嘴猫吃完金币,玩完卡牌之后心满意足,OH很是嫉妒,于是强迫大嘴猫完成以下任务:
给大嘴猫一个数(整数、小数、分数),让它找出该数的反转。
-
整数反转是将所有数位对调。
-
小数反转是把整数部分的数反转,再将小数部分的数反转,不交换整数部分与小数部分。
-
分数反转是把分母的数反转,再把分子的数反转,不交换分子与分母。
输入
一个非负数 s。
输出
一个数,即 s 的反转数。
样例输入 Copy
20220109
样例输出 Copy
90102202
提示
样例2:
输入:14.00
输出:41.0
样例3:
输入:13/14
输出:31/41
-
s是整数,不大于20位
-
s是小数,整数部分和小数部分均不大于10位
-
s是分数,分子和分母均不大于10位,数据分母保证不为0,不用约分
-
对于所有部分而言,如果除了0没有别的数,那么只保留一个0,注意前导零也要去掉
解析:反转(使用StringBuffer)并不难,只需要注意两个点:
1.前导零的处理:在本题中可将反转的字符串直接转化为int数据类型(也可以使用正则表达式),便可以解决前导零的问题。
2.使用split进行小数点切割时记得注意使用“\\.”。
import java.util.Scanner;
public class Main{
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner cin=new Scanner(System.in);
String s=cin.nextLine();
if(s.indexOf(".")!=-1) {
String ss[]=s.split("\\.");
// System.out.println(ss[0]);
StringBuffer sb=new StringBuffer(ss[0]);
sb.reverse();
int m=Integer.parseInt(ss[1]);
StringBuffer sb1=new StringBuffer(String.valueOf(m));
sb1.reverse();
int x=Integer.parseInt(sb1.toString());
System.out.println(Integer.parseInt(sb.toString())+"."+x);
}
else if(s.indexOf("/")!=-1) {
String ss[]=s.split("/");
StringBuffer sb=new StringBuffer(ss[0]);
sb.reverse();
StringBuffer sb1=new StringBuffer(ss[1]);
sb1.reverse();
System.out.println(Integer.parseInt(sb.toString())+"/"+Integer.parseInt(sb1.toString()));
}else {
StringBuffer sb=new StringBuffer(s);
sb.reverse();
System.out.println(Integer.parseInt(sb.toString()));
}
}
}
2892: 大嘴猫吃金币
地面上有排成一条直线的n个金币,金币有不同的价值(甚至是负的),大嘴猫想用它的大嘴来吃这些金币。但是大嘴猫只能张一次嘴,所以它只能吃连续一段的金币。你知道大嘴猫最多能吃多大价值的金币吗?
第一行一个整数n,表示有n个金币 。1 <= n <= 1000000。
接下来n行每行一个整数x,表示金币的价值。x在int范围内。
一行一个整数,表示最多吃下金币的价值。
4 1 2 -1 10
12
解析:因为是求一段区间的最大值,就需要我们对区间进行维护,那么保证sum<0时,sum=0即可
import java.util.Scanner;
public class Main{
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner cin=new Scanner(System.in);
int n=cin.nextInt();
long a[]=new long[n+1];
long ans=0;
long sum=0;
for(int i=1;i<=n;i++) {
a[i]=cin.nextLong();
if(sum+a[i]>=0)sum+=a[i];
else sum=0;
ans=Math.max(ans,sum);
}
System.out.println(ans);
}
}
2894: 通项公式
三角形数 | Tn= n(n + 1)/2 | 1,3,6,10,15… |
四边形数 | Fn= (n + 1)2 | 1,4,9,16,25… |
六边形数 | Hn= n(2n-1) | 1,6,15,28,45… |
可以验证的是,T49 = F34 = H25 = 1225。
import java.util.HashMap;
import java.util.Scanner;
public class Main{
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner cin=new Scanner(System.in);
int n=cin.nextInt();
HashMap<Long,Integer> map=new HashMap<>();
long a[]=new long[4];
for(int i=1;i<100005;i++) {
map.put((long) ((long)i*(2*i-1)),1);
}
int j=1;
for(int i=1;i<100005;i++) {
long x=(long)(i+1)*(long)(i+1);
if(map.containsKey(x)) {
a[j++]=x;
if(j==4)break;
}
}
System.out.println(a[n]);
}
}