说在前面:自己第一次写博客,嘿嘿,有点小兴奋
结果总结:队伍由于超时等多种原因,导致成绩并不理想,六道题,只做对了两道。。。
个人总结:遇到复杂的问题有想法但是苦于不知道如何去实现,还是敲代码的技巧太过生疏,奥里给!
C - Skill Up
基本题意:找出最少钱,能使他的每一列的和均达到X的值
不难想出,这本质上就是一个排列组合问题,然后分情况模拟就OK。
但关键就是如何实现?
import java.util.*;
public class Main{
public static void main(String[] args)
{
Scanner in=new Scanner(System.in);
int n=in.nextInt(),m=in.nextInt(),x=in.nextInt();
int[][] arr=new int[n][m+1];
for(int i=0;i<n;i++)
{
for(int j=0;j<=m;j++)
{
arr[i][j]=in.nextInt();
}
}
int ans=1000000007; //32位的最大质数
for(int i=1;i<(1<<n);i++) //二项式定理,你懂的
{
boolean f=true;
int[] ar=new int[m];
int sum=0;
for(int j=0;j<n;j++)
{
//找到挑的位置 难点!!
if((1&(i>>j))==1)
{
sum+=arr[j][0];
for(int k=1;k<=m;k++)
{
//建立k-1与k 列的映射关系,妙!
ar[k-1]+=arr[j][k]; //美妙的计算每一列的总和
}
}
}
for(int j=0;j<m;j++)
{
if(ar[j]<x)
f=false;;
}
if(f)
ans=Math.min(ans,sum);
if(ans==1000000007)
{
System.out.println(-1);
}
else
{
System.out.println(ans);
}
}
}
太爱这道题的 位运算!!
也是跟队员才了解学会到 这个C(m,n)的实现,想象:
000–111 这三个书架,你选择相当于放了1本书即为1 第二次位运算则是去判断这个书架到底有没有书。
还有 2^n 这个排列组合数学公式:体现在第一哥位运算
D - Teleporter
这道题大概意思就是有个闲着没事的时光老头穿梭时空,每到一个时空,就会给她一个神奇的数字,然后他TP到数字所指定的位置,一直K次
关键很简单,就是找出循环(还要找出前后点
import java.util.ArrayList;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt(); //N座城镇
long k = sc.nextLong(); //穿越K次
int[] array = new int[n];
//一步步读取数据,城镇轨迹
for(int i = 0 ; i < n; i++) {
array[i] = sc.nextInt();
}
//ord作为一个对照作用,来确定保存循环的位置!!
int[] ord = new int[n+1];
for(int i = 0; i < n + 1; i++) {
ord[i] = -1;
}
int now = 1;
//建立list用来保存特定点,循环前点与第一次循环圈
List<Integer> list = new ArrayList<>();
//个人感觉代码的关键部分。原来初始化-1在这里是为了当出现过那么就已经更新,而且,还获得了循环开始点ord[now]的位置。也为下一步求周期,size之差奠定基础
while(ord[now] == -1) {
ord[now] = list.size();
list.add(now);
now = array[now -1];//时时更新下一步要到哪里
}
int circle = list.size() - ord[now]; //周期
int length_begin = ord[now];
//判定就很简单了,
if(k < length_begin) {
System.out.println(list.get((int)k));
}else {
k -= length_begin;//这一步是要先减的不能直接除因为可能前点大于circle
k %= circle;
System.out.println(list.get((int)k+length_begin));
}
}
}
E - Colorful Blocks
意思:有N个块排在一行,M种颜色,求当他们相邻快颜色最多有K个不同时,求总共给多少种可能。
这个题还不是很懂,但是和排列组合有关。。。淦,写到这里突然懂了算法。
loop k1=0 to k:
ans+=c(n-1,k1)m(m-1)^(n-1-k1)
思路:n个数有n-1对,假设有k1个可以相同,那么第一个放颜色为m个,剩余就是(m-1)^(n-1-k1)个,但是由于k1所在位置不确定,因此再C挑选位置
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Scanner;
public final class Main {
private static final int MOD = 998244353;
static class Solver {
long[] factorial;
long[] facInverse;
long[] inverse;
void solve(int n, int m, int k) {
init(n);
int sum = 0;
for (int i = 0; i <= k; i++) {
final long edge = ncr(n - 1, i);
sum = (int) ((sum + (edge * (m * modpow(m - 1, n - 1 - i) % MOD)) % MOD) % MOD);
}
System.out.println(sum);
}
void init(int n) {
final int MAX = n + 2;
factorial = new long[MAX];
facInverse = new long[MAX];
inverse = new long[MAX];
factorial[0] = factorial[1] = 1;
facInverse[0] = facInverse[1] = 1;
inverse[1] = 1;
for (int i = 2; i < MAX; i++) {
factorial[i] = factorial[i - 1] * i % MOD;
final long inv = inverse[i] = MOD - inverse[MOD % i] * (MOD / i) % MOD;
facInverse[i] = facInverse[i - 1] * inv % MOD;
}
}
long ncr(int n, int r) {
if (n < r) { return 0; }
if (n < 0 || r < 0) { return 0; }
return factorial[n] * (facInverse[r] * facInverse[n - r] % MOD) % MOD;
}
long modpow(long a, long n) {
long res = 1;
while (n > 0) {
if (n % 2 == 1) {
res = res * a % MOD;
}
a = a * a % MOD;
n /= 2;
}
return res;
}
}
public static void main(String[] args) {
final Scanner in = new Scanner(new BufferedReader(new InputStreamReader(System.in)));
final int n = in.nextInt();
final int m = in.nextInt();
final int k = in.nextInt();
in.nextLine();
new Solver().solve(n, m, k);
}
}
F - Bracket Sequencing
这个题,想法就是,任意排列之后,是否可以得到有效括号序列
自己的想法是全排列之后再一个个判断合法括号。。。当然会超时
import java.util.*;
public class Main {
public static void main (String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
PriorityQueue<Paren> queue = new PriorityQueue<>();
for (int i = 0; i < n; i++) {
queue.add(new Paren(sc.next().toCharArray()));
}
long current = 0;
while (queue.size() > 0) {
Paren p = queue.poll();
if (current + p.min1 < 0) {
System.out.println("No");
return;
}
current += p.result;
}
if (current == 0) {
System.out.println("Yes");
} else {
System.out.println("No");
}
}
static class Paren implements Comparable<Paren> {
int result;
int min1;
int min2;
public Paren(char[] arr) {
min1 = 0;
result = 0;
for (char c : arr) {
if (c == '(') {
result++;
} else {
result--;
}
min1 = Math.min(min1, result);
}
min2 = min1 - result;
}
public int compareTo(Paren another) {
if (result > 0 && another.result > 0) {
return another.min1 - min1;
} else if (result > 0 && another.result <= 0) {
return -1;
} else if (result <= 0 && another.result > 0) {
return 1;
} else {
return min2 - another.min2;
}
}
}
}
我是一名小蓝鲸,这也是我写的第一篇博客
刚学不到两个月,F对我来说现阶段有些困难。。但也希望对看到的人有帮助,谢谢!
希望大家给我点一个赞,(●’◡’●)