日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

Java输出小明算对多少题目_2014年Java方向C组第十题

發布時間:2024/9/27 java 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Java输出小明算对多少题目_2014年Java方向C组第十题 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

標題:矩陣翻硬幣

小明先把硬幣擺成了一個 n 行 m 列的矩陣。

隨后,小明對每一個硬幣分別進行一次 Q 操作。

對第x行第y列的硬幣進行 Q 操作的定義:將所有第 ix 行,第 jy 列的硬幣進行翻轉。

其中i和j為任意使操作可行的正整數,行號和列號都是從1開始。

當小明對所有硬幣都進行了一次 Q 操作后,他發現了一個奇跡——所有硬幣均為正面朝上。

小明想知道最開始有多少枚硬幣是反面朝上的。于是,他向他的好朋友小M尋求幫助。

聰明的小M告訴小明,只需要對所有硬幣再進行一次Q操作,即可恢復到最開始的狀態。然而小明很懶,不愿意照做。于是小明希望你給出他更好的方法。幫他計算出答案。

【數據格式】

輸入數據包含一行,兩個正整數 n m,含義見題目描述。

輸出一個正整數,表示最開始有多少枚硬幣是反面朝上的。

【樣例輸入】

2 3

【樣例輸出】

1

【數據規模】

對于10%的數據,n、m <= 10^3;

對于20%的數據,n、m <= 10^7;

對于40%的數據,n、m <= 10^15;

對于100%的數據,n、m <= 10^1000(10的1000次方)。

資源約定:

峰值內存消耗(含虛擬機) < 256M

CPU消耗 < 2000ms

請嚴格按要求輸出,不要畫蛇添足地打印類似:“請您輸入...” 的多余內容。

所有代碼放在同一個源文件中,調試通過后,拷貝提交該源碼。

注意:不要使用package語句。不要使用jdk1.7及以上版本的特性。

注意:主類的名字必須是:Main,否則按無效代碼處理。

解析:

方案一:

題目中提示:“聰明的小M告訴小明,只需要對所有硬幣再進行一次Q操作,即可恢復到最開始的狀態。”

即假設所有格子硬幣都是正面的,反向進行上述分析的模擬。

Scanner input = new Scanner(System.in);

int n = input.nextInt(); //硬幣矩陣n行

int m = input.nextInt(); //硬幣矩陣m列

int[][] arr = new int[n+1][m+1]; //定義硬幣(數組大小+1的原因和題意相符,下標從1開始)

//將所有硬幣變成正面(1:正面;0:反面)

for (int x = 1; x <= n; x++) {

for (int y = 1; y <= m; y++) {

arr[x][y] = 1;

}

}

//模擬Q操作

for (int x = 1; x <= n; x++) {

for (int y = 1; y <= m; y++) {

//循環行號和列好的倍數

for (int i = 1; i*x <= n; i++) {

for (int j = 1; j*y<=m; j++) {

int temp = arr[i*x][j*y];

arr[i*x][j*y] = temp==1?0:1;

}

}

}

}

int count = 0; //假設反面的數量為0

for (int x = 1; x <= n; x++) {

for (int y = 1; y <= m; y++) {

if(arr[x][y] == 0)

count++;

}

}

System.out.println(count);

由于題目有專門的描述如下:

【數據規模】

對于10%的數據,n、m <= 10^3;

對于20%的數據,n、m <= 10^7;

對于40%的數據,n、m <= 10^15;

對于100%的數據,n、m <= 10^1000(10的1000次方)。

資源約定:

峰值內存消耗(含虛擬機) < 256M

CPU消耗 < 2000ms

則表示此題對執行效率有一定的要求,而進行方案一進行模擬的形式,如果數據量大的情況下,效率低,不能完全滿足題目的要求。

方案二:

假設硬幣舉證如下,模擬所有硬幣Q操作翻轉過程如下:

1 2 3

4 5 6

7 8 9

對第一個硬幣Q操作,需要翻轉硬幣:1,2,3,4,5,6,7,8,9(即全部)

對第二個硬幣Q操作,需要翻轉硬幣:2,5,8

對第三個硬幣Q操作,需要翻轉硬幣:3,6,9

對第四個硬幣Q操作,需要翻轉硬幣:4,5,6

對第五個硬幣Q操作,需要翻轉硬幣:5

對第六個硬幣Q操作,需要翻轉硬幣:6

對第七個硬幣Q操作,需要翻轉硬幣:7,8,9

對第八個硬幣Q操作,需要翻轉硬幣:8

對第九個硬幣Q操作,需要翻轉硬幣:9

思路:

(1)每個硬幣,如果知道被翻轉了幾次,則可以求出該硬幣初始狀態是正面還是反面,翻轉了奇數次硬幣初始為反面,翻轉了偶數次硬幣為正面。

(2)通過上述數據得出規律,翻轉次數=行號的約數個數*列號的約數個數,即:

第一個硬幣,行號為1(約數1,只有1個),列號為1(約數1,只有1個),翻轉數量=1*1=1

第二個硬幣,行號為1(約數1,只有1個),列號為2(約數1,2,有2個),翻轉數量=1*2=2

第三個硬幣,行號為1(約數1,只有1個),列號為3(約數1,3,有2個),翻轉數量=1*2=2

第四個硬幣,行號為2(約數1,2,有2個),列號為1(約數1,有1個),翻轉數量=2*1=2

第五個硬幣,行號為2(約數1,2,有2個),列號為2(約數1,2,有2個),翻轉數量=2*2=4

第六個硬幣,行號為2(約數1,2,有2個),列號為3(約數1,3,有2個),翻轉數量=2*2=4

第七個硬幣,行號為3(約數1,3,有2個),列號為1(約數1,有1個),翻轉數量=2*1=2

第八個硬幣,行號為3(約數1,3,有2個),列號為2(約數1,2,有2個),翻轉數量=2*2=4

第九個硬幣,行號為3(約數1,3,有2個),列號為3(約數1,3,有2個),翻轉數量=2*2=4

(3)實際上不需要求行號和列號的約數個數,只需要確定約數個數是奇數還是偶數即可,如何確定某個數字的約數個數是奇數還是偶數,有規律:平方數的約數個數是奇數,其它數字的約數個數為偶數,例如:

4約數(1,2,4)有三個為奇數;9的約數(1,3,9)有三個為奇數;16約數(1,2,4,8,16)有5個為奇數

5約束(1,5)有兩個為偶數;10約束(1,2,5,10)有四個為偶數;15約數(1,3,5,15)有四個為偶數

(4)翻轉次數=行號的約數個數*列號的約數個數;并且(奇乘奇=奇,奇乘偶=偶,偶乘偶=偶),當結果為奇數時,初始狀態才是反面,則要求行號約數個數和列號的約數個數都為奇數,則要求行號和列號都為平方數。

(5)即題目含義變成了求行號范圍內有幾個平方數,列號范圍內有幾個平方數,結果為兩個數字的乘積。

(6)如果循環遍歷行號和列號求含有平方數的個數,效率仍然很低下,有規律:某個數字內平方數的個數等于該數字的開方取整,例如:

9里面(1,4,9)三個平方數,9的開方也等于三;

20里面(1,4,9,16)四個平方數,20的開方然后取整等于四。

(7)我們得到結論:初始為反面的個數=行號的開方+列號的開方。

(8)由于行號和列號范圍可以為(10的1000次方),直接用數字類型無法表示,無法使用Math.sqrt進行開方,只能將數字做為字符串進行處理。

(9)當數字字符串的長度為偶數,則開方結果的長度為(本身長度/2);當數字字符串的長度為奇數,則開方結果的長度為(本身長度/2+1),例如:

99長度為2,開方取整為9,長度為1;100長度為3,開方結果為10,長度為2;

(10)確定了開方長度之后,利用BigInteger和char[]數組,確定數組每一位數字求出開方結果。

public static void main(String[] args) {

Scanner input = new Scanner(System.in);

String n = input.next(); //硬幣矩陣n行

String m = input.next(); //硬幣矩陣m列

BigInteger rowSqrt = sqrt(n);

BigInteger colSqrt = sqrt(m);

System.out.println(rowSqrt.multiply(colSqrt));

}

public static BigInteger sqrt(String s)

{

//數字字符串的長度為偶數,則開方結果的長度為(本身長度/2);

//當數字字符串的長度為奇數,則開方結果的長度為(本身長度/2+1)

int len = s.length() % 2 == 0 ? s.length()/2 : s.length()/2+1; //求開方之后的字符串長度

char[] arr = new char[len]; //定義字符數組用于存放開方后的字符串

Arrays.fill(arr,'0'); //將字符數組所有元素設置為'0'

BigInteger num = new BigInteger(s); //將字符串轉成BigInteger類型

for (int i = 0; i < arr.length; i++)

{

//循環確定字符數組每一位的數字

for (char c = '0'; c <= '9'; c++)

{

arr[i] = c;

BigInteger sqrtNum = new BigInteger(String.valueOf(arr));

if(sqrtNum.pow(2).compareTo(num) == 1) //當前假設數字的平方超過了數字本身,則減1操作

{

arr[i] -= 1;

break;

}

}

}

return new BigInteger(String.valueOf(arr));

}

總結

以上是生活随笔為你收集整理的Java输出小明算对多少题目_2014年Java方向C组第十题的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。