這次讓我們來看看總讓人頭疼的數數數的問題🤣🤣
一 大數處理之回文串😎
(撰稿人 brainstorm YYF)
題目描述
回文數是從前往后和從后往前得到的數是相同的,
現給你一個正整數N,請你找到比N大的最小的那個回文數P,
輸入
輸入包含多組測驗資料,
每組輸入一個正整數N,N不超過10000位,并且N不包含前導0,
輸出
對于每組輸入,輸出比N大的最小的那個回文數P,
樣例輸入 Copy
44
3
175
樣例輸出 Copy
55
4
181
? ? 首先看到這道題,注意到N是一個不超過10000位的整數,我的天哪,my god!!如此之大的數,顯然計算機中是沒有整型的資料型別能儲存這么大的數的,
? ? 那要考慮把這個小于10000位的數儲存起來,那顯然就是把這個數的每一位作為字符儲存起來,也就是將此數作為字串儲存起來,
char a[10001];
scanf("%s",&a);
注意到字串的結尾一定是一以‘\0’(’\0’的ASCII碼值為零)截止的,所以字串的長度一定要開的大于N的位數,我在此處開的是10001,其實為了一般保險起見,避免陣列越界等問題的出現,陣列最好開的更大一些,(字串其實就是字符陣列),
? ? 接下來的關鍵就是判斷回文串了,什么是回文串呢,也就是把一個數一劈兩半,從中間往前讀與從中間往后讀是一模一樣的,例如1234554321這個數,從中間劈開,前半部分是12345,后半部分是54321,前半部分從中間往前讀即是54321,與后半部分是相等的,所以此數即是回文串,
? ? 所以確定回文串即只用確定前半部分即可,只要前半部分確定,此回文串即確定,
? ? 既然涉及到一個數一劈兩半的程序,那么就要考慮到這個數的位數是奇還是偶,對于偶數位的數就像上面那個例子一樣,而對于奇數位的數則將最中間那個數不參與比較即可,而實際上,這兩種情況可以統一表示起來,
? ? 題目任務是找比N大的最小一位回文數,而想要它最小,改的數字越靠后越好,注意到這個要找的回文數不會小于前半部分+前半部分倒過來,例如16754382,比他大的最小回文數不會小于“1675”+“5761”,而5761>4382,則此數的最小回文數就是16755761,,
? ? 而對于另一種情況16325678,前半部分倒過來2361<5678 ,這個時候前半部分+前半部分倒過來是“1632”+“2361”,這個時候小于原本的數16325678,這時候如果把前半部分改成8765(后半部分倒過來),顯然是不對的,對于16325678這樣處理是87655678,是十分荒唐的,讀者可以舉例嘗試就可知了,記住我們的原則是改盡可能靠后的位的數,
? ? 這個時候該如何處理呢,把前半部分的最后一位進行加1處理,前半部分變成1633,這個時候再把前半部分+前半部分倒過來是“1633”+“3361”,即是最小的回文串16333361.
? ? 所以解決這道題的第一步即是判斷前半部分倒過來與后半部分比大小,不同的比較結果采用不同的處理方法,
#include<stdio.h>
#include<string.h>
int main()
{
char a[10001];
while(scanf("%s",&a)!=EOF)
{
int len,flag=1;
len=strlen(a);
for(int i=len/2-1;i>=0;i--)
{
if(a[i]>a[len-i-1])
{
flag=0;break;
}
else if(a[i]<a[len-i-1])
{
flag=1;break;
}
}
if(flag)
{
for(int i=(len-1)/2;i>=0;i--)
{
a[i]++;
if(a[i]>'9') a[i]='0';
else break;
}
if(a[0]=='0')
{
a[0]='1';
len++;
a[len/2]='0';
}
}
for(int i=0;i<=(len-1)/2;i++) printf("%c",a[i]);
for(int i=len/2-1;i>=0;i--) printf("%c",a[i]);
printf("\n");
}
return 0;
}
? ? 對了,提醒一句,要考慮到兩種特殊情況,1.找的是比N大的回文數,那么N=44時,最小的回文串為55 ,即是采用前半部分最后一位加一后再進行操作, 2.進行加一處理,那么9+1會變成0,往前再進一位,如果對于9999,那前半部分99會變成00,這個時候要把首位改成1,即變成10,長度加一,中間的一位變成0,即此回文串即為“10”+“0”+“01”,
? ? 最后的任務是將此回文串列印出來,回文串的前半部分已經確定,列印出前半部分+前半部分倒過來即是此回文串,
? ? 歐耶,終于寫完嘍!!!!😎😎😎
二 大數的解決實體之大數取余😎
(撰稿人Someday WWQ)
@[關于小帥的一個數學題]
#題目敘述如下:
既然是數學題,那么題面就要短,hx073269給你一個很大的數N,求它對P取模的結果,
輸入
輸入包含多組測驗用例,
每組測驗用例包含一個正整數N(0<N<10^10000) 和一個模數P(0<P<2^32)
輸出
對于每組測驗用例,輸出N%P
樣例輸入 Copy
10 30
30 10
100 33
樣例輸出 Copy
10
0
1
#我們知道無論是整型還是浮點型變數都無法存盤像N這么多位數的值,
int (16位) -32768~32767
long long或__int64(64位)
-9223372036854775808~9223372036854775807
float(32位) 精確到小數點后6~7位
double (64位) 精確到小數點后15~16位
因此要進行大數處理,利用字串存盤N,P可以用long int或long long 型變數存盤
char a[10001]={0};
long long int P;
scanf("%s %ld",a,&x);
之后我們利用回圈一位一位地計算,但是這里要注意的是必須計算一次就取模一次,
long long int n=0;
m=strlen(a);
for(i=0;i<m;i++){
n=n*10+(a[i]-'0');
n=n%x;
最后,因為是多樣例,所以每次我們都要將陣列中的元素清除,
memset(a,0,m);
最終代碼如下:
#include<stdio.h>
#include<string.h>
char a[10001]={0};
int main()
{
long long int m,n,i,x;
while(scanf("%s %ld",a,&x)!=EOF){
n=0;
m=strlen(a);
for(i=0;i<m;i++){
n=n*10+(a[i]-'0');
n=n%x;
}
printf("%ld\n",n);
memset(a,0,m);
}
return 0;
}
總結:大數問題一般都需要用字串處理,大數相加,相減,階乘,相除等等都是非常經典的問題,對于新手來說很值得多多練習,
這里轉發一個計算大數階乘的例子
三 魔方數問題😎
(撰稿人 sunkcost ZS)
撰寫程式列印n*n的魔方矩陣,1,2,…n的方陣排列,且每行,每列和每條對角線上的和都相等,由用戶指定n的值
17 24 1 8 15
23 5 7 14 16
4 6 13 20 22
10 12 19 21 3
11 18 25 2 9
#include<stdio.h>
int a[100][100];
int main()
{
int row,line,i;
int n;
scanf("%d",&n);
row=0;
line=n/2;//首先奇數的列印
if(n%2!=0){
for(i=1;i<=n*n;i++)
{
if(a[row][line]!=0)
{
row=(row+2)%n;
line=(line-1+n)%n;
}
a[row][line]=i;
row=(row-1+n)%n;
line=(line+1)%n;
}
}
else { //偶數的列印
int i=1;
for(row=0;row<n;row++){
for(line=0;line<n;line++){
if((row+1)%4!=(line+1)%4&&((row+1)%4+(line+1)%4)!=1){
a[row][line]=i;
}
i++;
}
}
i--;
for(row=0;row<n;row++){
for(line=0;line<n;line++){
if((row+1)%4==(line+1)%4||((row+1)%4+(line+1)%4)==1){
a[row][line]=i;
}
i--;
}
}
}
for(int k=0;k<n;k++){
for(int j=0;j<n;j++){
printf("%4d ",a[k][j]);
}
printf("\n");
}
return 0;
}
魔方數有個重要的點就是要分奇數與偶數,奇數相對來說比較容易,只需要找準1的位置,依次找規律遍歷所有n的平方以內的數,還是比較容易的,
那么關鍵來了,偶數怎么處理?偶數對需要兩次大的回圈,實際上還是判斷條件對每個數進行賦值,例如我這里就是利用每次行與列的關系進行判斷來調整每次的值,
總結一下奧,還是每次對n平方以內數的安排順序,所以還是不懂?😂
再說簡單一點就是奇數每次上下遍歷,偶數是行列每次對4的關系進行賦值,
本次小編就總結到這了,希望大家喜歡哈!記得一鍵關注,下期分析敬請期待😘
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/235486.html
標籤:其他
下一篇:阿菊的OpenCv11——cv2讀取影像并用matplotlib(plt)顯示多幅影像以及RGB影像通道的拆分(cv2.split)與合并(cv2.merge)
