codeforeces:Mister B and Astronomers分析和实现
题目很长,稍微翻译一下:
外星球每隔T秒中只有一秒可以被观测到,其它T-1秒无法被观测。n个天文学家(分别编号为1,...,n)轮流观测天空1秒,且第i+1个科学家在第i个天文学家后ai+1秒后才执行观测,而第一个天文学家则在第n个天文学家后a1秒后才执行观测,且第一个天文学家在0秒时执行第一次观测(即第一个天文学家观测的时间是[0,1),第二个科学家在[a2,a2+1)时观测,而最后一个天文学家在[a2+a3+...+an-1,a2+a3+...+an-1+1)时观测,之后再过a1秒后第一个天文学家继续观测)。
由于外星球具体在首次观测之后的T秒中的哪一秒出现是不确定的,若外星球在[i, i+1)时出现(0<=i<T-1),且天文学家j是首个观测到星球的人,则称j抢占了[i,i+1)时间片段。
已知T,n,a1,....,an其中(1<=T<=1e9,1<=n<=1e5,1<=a1,...,an<=1e9)。输出每个天文学家所抢占的时间片段数。
有趣的问题,说一下我的解法:
首先记L=a1+...+an,这表示一个观测轮回耗时,每个天文学家总是在观测开始的L秒后开始下一次观测,记每个天文学家第一次观测的时间分别发生于t1,...,tn。
首先说明一个重要的定理:若天文学家a在第i秒与天文学家b在第j秒均观测到了[x,x+1)时间片段,且i<j,那么天文学家b将再也不能抢占新的时间片段。原因很简单,其后续观测的步骤[x+L,x+L+1),...均被天文学家a观测过了,我们可以称b与j秒时追尾了a。实际上若b首次追尾a,则b此时所观察的时间片必定是天文学家a第一次观察的那一个时间片。因为若b在第j秒观察到了a第i秒观察的同一时间片,若a在第i秒之前还进行了一次观察,则b在第j-L秒时就会观测到了a在第i-j秒观察的时间片。
记c为T和L的最大公约数,而由于i*T+j*L=k*c,即c|(i*T%L),因此可以将T切分为c个环,其中环i(0<=i<c)包含时间点序列:i,c+i,2c+i,...,T-c+i。显然任意一个天文学家的观测(起始)时间必然会落在某个特定环中。假设其某次观测时间落于环i中,比如说时间为k*c+i,那么显然上一次观测时间点为(k*c+i-c)%T,下一次为(k*c+i+c)%T,均落在环i中,由此知道该天文学家所观测的时间点必然落于上述某个环中。
我们需要先将n个天文学家分配到c个环中,按照其第一次观测时间对c的模值判断到底落在哪一个环中。这里可以用一株红黑树,红黑树中每个结点的关键字为环号,而结点的值为一个数组,保存了所有落于环中的对象。这样的操作需要的时间复杂度为O(nlog2(n)),而空间复杂度为O(n)。
之后我们仅考虑对某个环进行具体的观察,并将对这个环的观察推广到所有的环上。假定我们观察包含至少一个天文学家的环i。根据欧几里德算法的推广(详情可以见我所写的博客欧几里德算法(最大公约数算法)完整分析),能找到公式xa+yb=c,其中c是a和b的最大公约数,而x与y均是整数。代入a=L,b=T,则可以改写为xT+yL=c,换言之(yL)%x=c,即任意一个天文学家在第y次观测时就能观测到环中的下一个时间点,这也意味着如果还存在其它天文学家,则必定会发生追尾现象。取任意一个天文学家s0,并以其首次观测时间为基准,记为循环次数0(第i次循环的观测的时间为ts0+iL),而按照其首次追尾的天文学家的先后顺序(即在第几次观测时发生首次追尾)对关联到同一个环的其余天文学家进行排序。
首先说明如何能够快速计算天文学家i被天文学家j首次追尾时间,其中天文学家i和j关联于同一个环。欧几里德算法中提供了如何高效计算ax+by=kc的方案,其中c是a和b的最大公约数,且x,y,k均为整数,而k是正整数,x是满足上述条件的最小非负整数。因此我们能找到这样的公式xL+yT=(ti-ty)%T,即(xL)%T=(tj-ti)%T,其中x是最小非负整数,x也正是天文学家i首次追尾天文学家j的观测次数。由于c是被提前计算出来的,而要找这样的x所花费的时间为O(1)。
这样我们就能快速计算出同一个环关联的每个天文学家被天文学家s追尾的时刻,并按照这些信息进行归并排序。这样就能得到了一个有序的序列s0,s1,...,sm。而si所抢占的时间片为s0首次追尾si+1的循环次数减去s0首次追尾si的循环次数。这是因为s0所经过的步骤,同一个环中的其他天文学家也会相应地经历,以相同的步骤,相同的先后顺序,只是发生在不同的时间点而已。因此当s0观测首次追尾si后在的k次循环时又再次追尾了si+1,则si在k次循环时也必定会追尾si+1。而由于在追尾si和追尾si+1期间s0没有追尾其他人,因此si追尾的第一个人必定是天文学家si+1。而一个天文学家所抢占的时间片恰好就是其在第一次循环一直到首次追尾所经历的循环次数,因为在首次追尾之前,他总是能在每次循环时抢占到未被抢占的时间片。
若一个环中对应m个天文学家,那么计算这个环对应的所有天文学家所抢占的时间片数的时间复杂度为O(1)*m+mlog2(m)+O(1)*m=mlog2(m),其中O(1)*m分别为计算被s0首次追尾的循环次数,以及计算抢占时间片花费的时间,而mlog2(m)是归并排序m个天文学家所花费的时间。
假设c个环分别关联v0,v1,...,vc个天文学家,而v0+v1+...+vc=n。因此花费的总时间是O(nlog2(n))+O(v0log2(v0))+...+O(vclog2(vc))<=O(nlog2(n))+O((v0+...+vc)log2(n))=O(nlog2(n))+O(nlog2(n))=O(nlog2(n))。而空间复杂度为O(n),考虑了红黑树占用的空间和数组占用的空间。
给出AC的java代码:
package cn.dalt.codeforces; import java.io.BufferedInputStream; import java.io.IOException; import java.io.InputStream; import java.io.PushbackInputStream; import java.math.BigDecimal; import java.math.BigInteger; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.TreeMap; /** * Created by Administrator on 2017/7/4. */ public class MisterBAndAstronomers { public static void main(String[] args) throws IOException { AcmInputReader reader = new AcmInputReader(System.in); //Read all input int T = reader.nextInteger(); int n = reader.nextInteger(); AstronomerNode[] astronomerNodes = new AstronomerNode[n]; astronomerNodes[0] = new AstronomerNode(0); astronomerNodes[0].startTime = 0; int firstTakeTime = reader.nextInteger(); int L = 0; for (int i = 1; i < n; i++) { int wi = reader.nextInteger(); L = (L + wi) % T; astronomerNodes[i] = new AstronomerNode(i); astronomerNodes[i].startTime = L; } L = (L + firstTakeTime) % T; //Link all astronomer with cycles int c = DiscreteMath.gcd(T, L); TreeMap<Integer, List<AstronomerNode>> map = new TreeMap<Integer, List<AstronomerNode>>(); for (int i = 0; i < n; i++) { Integer cycleId = astronomerNodes[i].startTime % c; List<AstronomerNode> list = map.get(cycleId); if (list == null) { list = new ArrayList<>(); map.put(cycleId, list); } list.add(astronomerNodes[i]); } int[] coe = DiscreteMath.axPlusByEqualToZeroCoefficients(L, T, c); int q = coe[0]; int w = coe[1]; coe = DiscreteMath.axPlusByEqualToCCoefficients(L, T); coe = DiscreteMath.minimizeXOfAxPlusByEqualToZEquation(coe[0], coe[1], q, w); int x = (int)coe[0]; int y = (int)coe[1]; for (List<AstronomerNode> list : map.values()) { AstronomerNode base = list.get(0); base.loopCount = 0; for (int i = 1, bound = list.size(); i < bound; i++) { AstronomerNode node = list.get(i); int offset = node.startTime - base.startTime; if (offset < 0) { offset += T; } int loopCount = offset / c; int[] minCoe = DiscreteMath.minimizeXOfAxPlusByEqualToZEquation((long)x * loopCount, (long)y * loopCount, q, w); node.loopCount = minCoe[0]; } Collections.sort(list); AstronomerNode lastNode = list.get(0); for(int i = 1, bound = list.size(); i < bound; i++) { AstronomerNode curNode = list.get(i); lastNode.timePieceCount = curNode.loopCount - lastNode.loopCount; lastNode = curNode; } lastNode.timePieceCount = q - lastNode.loopCount; } for(AstronomerNode node : astronomerNodes) { System.out.print(node.timePieceCount); System.out.print(' '); } } private static class AstronomerNode implements Comparable<AstronomerNode> { public int id; public int timePieceCount; public int loopCount; public int startTime; public AstronomerNode(int id) { this.id = id; } @Override public int compareTo(AstronomerNode o) { int res = this.loopCount - o.loopCount; if (res == 0) { return o.id - this.id; } return res; } } /** * Created by dalt on 2017/7/4. */ private static final class DiscreteMath { private DiscreteMath() { } ; /** * Calculate the greatest common divisor of a and b * * @param a a non-negative integer * @param b a non-negative integer or a positive integer if a == 0 * @return the greatest common divisor of a and b */ public static int gcd(int a, int b) { if (a < 0 || b < 0 || (a + b <= 0)) { throw new IllegalArgumentException(); } if (a >= b) { return gcdInner(a, b); } return gcdInner(b, a); } private static int gcdInner(int a, int b) { if (b == 0) { return a; } return gcdInner(b, a % b); } /** * Calculate a possible coefficent(x,y) of equation xa + yb = c, and {@code c=gcd(a,b)} * * @param a a non-negative integer * @param b a non-negative integer or a positive integer if a == 0 * @return an array contains integer, the first element represent x and the second one is y. */ public static int[] axPlusByEqualToCCoefficients(int a, int b) { if (a < 0 || b < 0 || (a + b <= 0)) { throw new IllegalArgumentException(); } if (a >= b) { return axPlusByEqualToCCoefficientsInner(a, b); } int[] r = axPlusByEqualToCCoefficientsInner(b, a); int rx = r[0]; r[0] = r[1]; r[1] = rx; return r; } private static int[] axPlusByEqualToCCoefficientsInner(int a, int b) { if (b == 0) { return new int[]{1, 0}; } int[] r = axPlusByEqualToCCoefficientsInner(b, a % b); int rx = r[0]; r[0] = r[1]; r[1] = rx - r[1] * (a / b); return r; } /** * Calculate coefficent(x,y) of equation xa + yb = 0, and {@code c=gcd(a,b)}, * and the returned x is the minimun postive integer of all posible x, the same rule for y. * * @param a a non-negative integer * @param b a non-negative integer or a positive integer if a == 0 * @return an array contains integer, the first element represent x and the second one is y. */ public static int[] axPlusByEqualToZeroCoefficients(int a, int b) { return axPlusByEqualToZeroCoefficients(a, b, gcd(a, b)); } /** * Calculate coefficent(x,y) of equation xa + yb = 0, and {@code c=gcd(a,b)}, * and the returned x is the minimun postive integer of all posible x, the same rule for y. * This method is faster than {@link #axPlusByEqualToCCoefficients(int, int)} * * @param a a non-negative integer * @param b a non-negative integer or a positive integer if a == 0 * @param c the greatest common divisor of a and b * @return an array contains integer, the first element represent x and the second one is y. */ public static int[] axPlusByEqualToZeroCoefficients(int a, int b, int c) { return new int[]{b / c, a / c}; } /** * Minimize such coefficient as x,y suffice for equation xa + yb = z.This method try to minize x as an positive integer. * * @param x coefficient * @param y coefficient * @param i the first element of axPlusByEqualToZeroCoefficients(a, b) * @param j the second element of axPlusByEqualToZeroCoefficients(a, b) * @return the minimized x and corresponding y */ public static int[] minimizeXOfAxPlusByEqualToZEquation(long x, long y, int i, int j) { if (x < 0) { return new int[]{(int)(x % i + i), (int)(y - (x / i + 1) * j)}; } return new int[]{(int)(x % i), (int)(y - x / i * j)}; } } /** * @author dalt * @see java.lang.AutoCloseable * @since java1.7 */ private static class AcmInputReader implements AutoCloseable { private PushbackInputStream in; /** * 创建读取器 * * @param input 输入流 */ public AcmInputReader(InputStream input) { in = new PushbackInputStream(new BufferedInputStream(input)); } @Override public void close() throws IOException { in.close(); } private int nextByte() throws IOException { return in.read() & 0xff; } /** * 如果下一个字节为b,则跳过该字节 * * @param b 被跳过的字节值 * @throws IOException if 输入流读取错误 */ public void skipByte(int b) throws IOException { int c; if ((c = nextByte()) != b) { in.unread(c); } } /** * 如果后续k个字节均为b,则跳过k个字节。这里{@literal k<times} * * @param b 被跳过的字节值 * @param times 跳过次数,-1表示无穷 * @throws IOException if 输入流读取错误 */ public void skipByte(int b, int times) throws IOException { int c; while ((c = nextByte()) == b && times > 0) { times--; } if (c != b) { in.unread(c); } } /** * 类似于{@link #skipByte(int, int)}, 但是会跳过中间出现的空白字符。 * * @param b 被跳过的字节值 * @param times 跳过次数,-1表示无穷 * @throws IOException if 输入流读取错误 */ public void skipBlankAndByte(int b, int times) throws IOException { int c; skipBlank(); while ((c = nextByte()) == b && times > 0) { times--; skipBlank(); } if (c != b) { in.unread(c); } } /** * 读取下一块不含空白字符的字符块 * * @return 下一块不含空白字符的字符块 * @throws IOException if 输入流读取错误 */ public String nextBlock() throws IOException { skipBlank(); StringBuilder sb = new StringBuilder(); int c = nextByte(); while (AsciiMarksLazyHolder.asciiMarks[c = nextByte()] != AsciiMarksLazyHolder.BLANK_MARK) { sb.append((char) c); } in.unread(c); return sb.toString(); } /** * 跳过输入流中后续空白字符 * * @throws IOException if 输入流读取错误 */ private void skipBlank() throws IOException { int c; while ((c = nextByte()) <= 32) ; in.unread(c); } /** * 读取下一个整数(可正可负),这里没有对溢出做判断 * * @return 下一个整数值 * @throws IOException if 输入流读取错误 */ public int nextInteger() throws IOException { skipBlank(); int value = 0; boolean positive = true; int c = nextByte(); if (AsciiMarksLazyHolder.asciiMarks[c] == AsciiMarksLazyHolder.SIGN_MARK) { positive = c == '+'; } else { value = '0' - c; } c = nextByte(); while (AsciiMarksLazyHolder.asciiMarks[c] == AsciiMarksLazyHolder.NUMERAL_MARK) { value = (value << 3) + (value << 1) + '0' - c; c = nextByte(); } in.unread(c); return positive ? -value : value; } /** * 判断是否到了文件结尾 * * @return true如果到了文件结尾,否则false * @throws IOException if 输入流读取错误 */ public boolean isMeetEOF() throws IOException { int c = nextByte(); if (AsciiMarksLazyHolder.asciiMarks[c] == AsciiMarksLazyHolder.EOF) { return true; } in.unread(c); return false; } /** * 判断是否在跳过空白字符后抵达文件结尾 * * @return true如果到了文件结尾,否则false * @throws IOException if 输入流读取错误 */ public boolean isMeetBlankAndEOF() throws IOException { skipBlank(); int c = nextByte(); if (AsciiMarksLazyHolder.asciiMarks[c] == AsciiMarksLazyHolder.EOF) { return true; } in.unread(c); return false; } /** * 获取下一个用英文字母组成的单词 * * @return 下一个用英文字母组成的单词 */ public String nextWord() throws IOException { StringBuilder sb = new StringBuilder(16); skipBlank(); int c; while ((AsciiMarksLazyHolder.asciiMarks[(c = nextByte())] & AsciiMarksLazyHolder.LETTER_MARK) != 0) { sb.append((char) c); } in.unread(c); return sb.toString(); } /** * 读取下一个长整数(可正可负),这里没有对溢出做判断 * * @return 下一个长整数值 * @throws IOException if 输入流读取错误 */ public long nextLong() throws IOException { skipBlank(); long value = 0; boolean positive = true; int c = nextByte(); if (AsciiMarksLazyHolder.asciiMarks[c] == AsciiMarksLazyHolder.SIGN_MARK) { positive = c == '+'; } else { value = '0' - c; } c = nextByte(); while (AsciiMarksLazyHolder.asciiMarks[c] == AsciiMarksLazyHolder.NUMERAL_MARK) { value = (value << 3) + (value << 1) + '0' - c; c = nextByte(); } in.unread(c); return positive ? -value : value; } /** * 读取下一个浮点数(可正可负),浮点数是近似值 * * @return 下一个浮点数值 * @throws IOException if 输入流读取错误 */ public float nextFloat() throws IOException { return (float) nextDouble(); } /** * 读取下一个浮点数(可正可负),浮点数是近似值 * * @return 下一个浮点数值 * @throws IOException if 输入流读取错误 */ public double nextDouble() throws IOException { skipBlank(); double value = 0; boolean positive = true; int c = nextByte(); if (AsciiMarksLazyHolder.asciiMarks[c] == AsciiMarksLazyHolder.SIGN_MARK) { positive = c == '+'; } else { value = c - '0'; } c = nextByte(); while (AsciiMarksLazyHolder.asciiMarks[c] == AsciiMarksLazyHolder.NUMERAL_MARK) { value = value * 10.0 + c - '0'; c = nextByte(); } if (c == '.') { double littlePart = 0; double base = 1; c = nextByte(); while (AsciiMarksLazyHolder.asciiMarks[c] == AsciiMarksLazyHolder.NUMERAL_MARK) { littlePart = littlePart * 10.0 + c - '0'; base *= 10.0; c = nextByte(); } value += littlePart / base; } in.unread(c); return positive ? value : -value; } /** * 读取下一个高精度数值 * * @return 下一个高精度数值 * @throws IOException if 输入流读取错误 */ public BigDecimal nextDecimal() throws IOException { skipBlank(); StringBuilder sb = new StringBuilder(); sb.append((char) nextByte()); int c = nextByte(); while (AsciiMarksLazyHolder.asciiMarks[c] == AsciiMarksLazyHolder.NUMERAL_MARK) { sb.append((char) c); c = nextByte(); } if (c == '.') { sb.append('.'); c = nextByte(); while (AsciiMarksLazyHolder.asciiMarks[c] == AsciiMarksLazyHolder.NUMERAL_MARK) { sb.append((char) c); c = nextByte(); } } in.unread(c); return new BigDecimal(sb.toString()); } /** * 读取下一个大整数数值 * * @return 下一个大整数数值 * @throws IOException if 输入流读取错误 */ public BigInteger nextBigInteger() throws IOException { skipBlank(); StringBuilder sb = new StringBuilder(); sb.append((char) nextByte()); int c = nextByte(); while (AsciiMarksLazyHolder.asciiMarks[c] == AsciiMarksLazyHolder.NUMERAL_MARK) { sb.append((char) c); c = nextByte(); } in.unread(c); return new BigInteger(sb.toString()); } private static class AsciiMarksLazyHolder { public static final byte BLANK_MARK = 1; public static final byte SIGN_MARK = 1 << 1; public static final byte NUMERAL_MARK = 1 << 2; public static final byte UPPERCASE_LETTER_MARK = 1 << 3; public static final byte LOWERCASE_LETTER_MARK = 1 << 4; public static final byte LETTER_MARK = UPPERCASE_LETTER_MARK | LOWERCASE_LETTER_MARK; public static final byte EOF = 1 << 5; public static byte[] asciiMarks = new byte[256]; static { for (int i = 0; i <= 32; i++) { asciiMarks[i] = BLANK_MARK; } asciiMarks['+'] = SIGN_MARK; asciiMarks['-'] = SIGN_MARK; for (int i = '0'; i <= '9'; i++) { asciiMarks[i] = NUMERAL_MARK; } for (int i = 'a'; i <= 'z'; i++) { asciiMarks[i] = LOWERCASE_LETTER_MARK; } for (int i = 'A'; i <= 'Z'; i++) { asciiMarks[i] = UPPERCASE_LETTER_MARK; } asciiMarks[0xff] = EOF; } } } }
codeforeces:Mister B and Astronomers分析和实现的更多相关文章
- 【CF819D】Mister B and Astronomers EXGCD
[CF819D]Mister B and Astronomers 题意:小鼠Jack想当太空人(哦不,太空鼠)!为此,它在夜晚带领一堆小朋友一起来到户外看星星.一共有 $n$ 只小鼠,这些小鼠围成一 ...
- CF D.Mister B and Astronomers
题意概括好麻烦, 好吧既然是英文题面那放一下题意. 题意:有 n 个观察员,第一个观察员在 0 秒开始观察星空,随后第i 个观察员会在第 i − 1 个观察员之后 ai 秒观察,第一个观察员也会在第 ...
- alias导致virtualenv异常的分析和解法
title: alias导致virtualenv异常的分析和解法 toc: true comments: true date: 2016-06-27 23:40:56 tags: [OS X, ZSH ...
- 火焰图分析openresty性能瓶颈
注:本文操作基于CentOS 系统 准备工作 用wget从https://sourceware.org/systemtap/ftp/releases/下载最新版的systemtap.tar.gz压缩包 ...
- 一起来玩echarts系列(一)------箱线图的分析与绘制
一.箱线图 Box-plot 箱线图一般被用作显示数据分散情况.具体是计算一组数据的中位数.25%分位数.75%分位数.上边界.下边界,来将数据从大到小排列,直观展示数据整体的分布情况. 大部分正常数 ...
- 应用工具 .NET Portability Analyzer 分析迁移dotnet core
大多数开发人员更喜欢一次性编写好业务逻辑代码,以后再重用这些代码.与构建不同的应用以面向多个平台相比,这种方法更加容易.如果您创建与 .NET Core 兼容的.NET 标准库,那么现在比以往任何时候 ...
- UWP中新加的数据绑定方式x:Bind分析总结
UWP中新加的数据绑定方式x:Bind分析总结 0x00 UWP中的x:Bind 由之前有过WPF开发经验,所以在学习UWP的时候直接省略了XAML.数据绑定等几个看着十分眼熟的主题.学习过程中倒是也 ...
- 查看w3wp进程占用的内存及.NET内存泄露,死锁分析
一 基础知识 在分析之前,先上一张图: 从上面可以看到,这个w3wp进程占用了376M内存,启动了54个线程. 在使用windbg查看之前,看到的进程含有 *32 字样,意思是在64位机器上已32位方 ...
- ZIP压缩算法详细分析及解压实例解释
最近自己实现了一个ZIP压缩数据的解压程序,觉得有必要把ZIP压缩格式进行一下详细总结,数据压缩是一门通信原理和计算机科学都会涉及到的学科,在通信原理中,一般称为信源编码,在计算机科学里,一般称为数据 ...
随机推荐
- Compile For Cydia Submission Author: BigBoss Updated September 23, 2011
Compile For Cydia Submission Author: BigBoss Updated September 23, 2011: In order to submit your app ...
- Asphyre Sphinx is a cross-platform framework for developing 2D/3D video games and interactive business applications
Introduction Introduction Asphyre Sphinx is a cross-platform framework for developing 2D/3D video ga ...
- 【MFC】MFC中窗口重绘
MFC中窗口重绘 摘自:http://blog.csdn.net/shuilan0066/article/details/5859057 在刷新窗口时经常要调用重绘函数 MFC提供了三个函数用于窗口重 ...
- MySql必知必会实战练习(一)表创建和数据添加
1.实战环境 windows 10 64位 mysql-8.0.13 mysql编辑和查看工具:NaviCat for MySql 表脚本文件: ########################### ...
- IDEA Intellij中vim插件使用小技巧
在 IDEA Intellij小技巧和插件 一文中简单介绍了一下IdeaVim插件.在这里详细总结一下这个插件在日常编程中的一些常用小技巧.供有兴趣使用这个插件,但对Vim还不十分熟悉的朋友参考.当然 ...
- 1132. Cut Integer (20)
Cutting an integer means to cut a K digits long integer Z into two integers of (K/2) digits long int ...
- ORA-12154,TNS错误解决办法
- SQL TINYINT 1 讨论记录
SQL TINYINT 1 讨论记录 群里有一位小伙伴又和他上司怒上了,关于 TINYINT 1 的问题. 这里记录一下,TINYINT 无符号可以是 0~255,而这里的 长度 1只是长度,并不是存 ...
- Java之父职场路
Java之父——詹姆斯·高斯林出生于加拿大,是一位计算机编程天才.在卡内基·梅隆大学攻读计算机博士学位时,他编写了多处理器版本的Unix操作系统,是JAVA编程语言的创始人.1991年,在Sun公司工 ...
- JDBC预编译语句表名占位异常
有时候,我们有这样的需求,需要清空多个表的内容,这样我们有两种做法,可用delete from table 或 truncate table table,两种方法视情况而定,前者只是一条条的删除表数据 ...