2018演算法課習題(一)

2021-08-26 20:19:14 字數 3875 閱讀 9270

目錄:

數字統計問題

2011的倍數

最多約數問題

最大間隙問題

字典序問題

金幣列陣問題

更新中......

時間限制: 1 sec  記憶體限制: 128 mb

提交: 8  解決: 6

[提交] [狀態] [討論版] [命題人:admin]

題目描述

給定一本書,其中包含n頁,計算出書的全部頁碼中用到了多少個數字0…9?頁碼從1開始

輸入乙個整數n,代表頁碼總數。(0<=n<=109)

輸出十行,每行乙個整數,分別表示0~9每個數字出現的次數

樣例輸入

11
樣例輸出

141

1111

111

提示

注意!答案範圍可能超過int儲存範圍。

[提交][狀態]

【分析】

1. 暴力思路。列舉從1到n每乙個數字,對於i,分解這個數字每一位,數一數即可。

2. 組合數學計數。考慮每一位放數字0~9,存在的數字數量。

比如n=12345,在中間那乙個3的位置,

如果放1(小於3),那麼種數=(12+1)*100,高位00~12,低位00~99

如果放3(等於3),那麼種數=12*100+45+1,高位00~11,低位00~99,加上,高位12,低位00~45

如果放8(大於3),那麼種數=12*100, 高位00~11,低位00~99

對於每一位,列舉放0~9,統計數量即可。

特別注意,上面的統計方法會統計前導0,最後要減掉帶前導0的數量

【**】

#includetypedef long long ll;

ll cnt[10]=;

ll bit[12];

int main()

}for(int i=top-1;i>=0;i--) //由於上面列舉0時,0會作為前導0,因此減掉個位前導0的次數

cnt[0]-=bit[i];

for(int i=0;i<10;i++)

printf("%lld\n",cnt[i]);

return 0;

}

時間限制: 1 sec  記憶體限制: 128 mb

提交: 9  解決: 6

[提交] [狀態] [討論版] [命題人:admin]

題目描述

給定乙個正整數n,多少個1組成的整數可以被n整除?

輸入乙個整數n(1<=n<=10^5) 

輸出乙個正整數,表示數字1的個數。如果無解,請輸出-1

樣例輸入

2011
樣例輸出

670
[提交][狀態]

【分析】

同餘模定理:(a+b)%n=(a%n+b%n)%n;   a*b%n=a%n*b%n

一般思路,暴力乘10再加1,直到模除2011等於0。但是數字太大時,c語言不提供大數儲存。

令res表示答案,初始為1。狀態轉移:res=res*10+1,我們要求的是res%n的值,因此狀態轉移後,讓res模除n,對結果是無影響的。

如何判斷無解:用vis陣列標記每個數字對模除n的餘數是否出現過,如果出現過,再次碰到,說明形成了迴圈,永遠找不到模除n等於0的數。

【**】

#includebool vis[200000];

int main()

vis[p]=true;

p=(p*10+1)%n;

ans++;

}if(ans==-1)

printf("-1\n");

else

printf("%d\n",ans);

return 0;

}

時間限制: 1 sec  記憶體限制: 128 mb

提交: 19  解決: 8

[提交] [狀態] [討論版] [命題人:admin]

題目描述

正整數 x 的約數是能整除x的正整數,其約數的個數記為div(x),例如div(10)=4。設 a 和 b 是兩個正整數,找出 a 和 b 之間(包含a,b)約數個數最多的數 x 的約數個數

輸入兩個正整數a和b,(1<=a<=b<=105)

輸出乙個正整數表示答案。

樣例輸入

1 36
樣例輸出

9
[提交][狀態]

【分析】

對於乙個數字x,求其因子個數,一般思路,迴圈1到n,只要模除等於0,即為因子,時間複雜度o(n),優化思路:迴圈到1到sqrt(n),因為對於x的因子a,若asqrt(n),使得a*b=n。若sqrt(n)恰好是個整數,也將是乙個因子。時間複雜度o(sqrt(n))

迴圈a到b,找出最大因子數即可。總時間複雜度o(n*sqrt(n))

【**】

#includeusing namespace std;

int get(int x)

return res;

}int main()

printf("%d\n",ans);

}

時間限制: 9 sec  記憶體限制: 1024 mb

提交: 34  解決: 7

[提交] [狀態] [討論版] [命題人:admin]

題目描述

給定 n 個實數,求這n個實數在數軸上相鄰2個數之間的最大差值,設計解最大間隙問題的線性時間演算法(時間複雜度為o(n))。

輸入第一行乙個正整數n(2<=n<=2×107)

第二行n個實數,資料保證這些實數只有一位小數。

輸出乙個實數,保留1位小數。

樣例輸入

5

2.3 3.1 7.5 1.5 6.3

樣例輸出

3.2
[提交][狀態]

【分析】

鴿籠原理:將n個鴿子放到n+1個籠子裡,不管怎麼放,必然至少有乙個籠子是空的。

對於輸入的n個數字,找到最大值最小值,還剩下n-2個數字,將其放到n-1個區間裡,則必然有空區間。

最大間隙一定出現在空區間附近。有可能多個空區間連在一起。

分塊n-1個區間,每個區間儲存區間內的最大值和最小值。

掃瞄放好的數軸,記錄下最大的空隙即可。總時間複雜度o(3n)

【**】

#includeusing namespace std;

const int n=2e7+5;

double max[n],min[n],a[n];

int n;

int main()}}

int t;

char s[10];

scanf("%d",&t);

while(t--)

void changerow(int x) //對temp陣列翻轉第x行

int checkcol(int x,int y) //檢查temp第k列和aim的第p列是否相同

int main()

for(int i=1;i<=n;i++)

int ans=inf;

for(int j=1;j<=m;j++) //列舉將第j列作為第一列

for(int i=1;i<=n;i++)

}for(int k=2;k<=m;k++) //考慮調整後面的列

else}}

if(res!=-1&&resans=res;

}if(ans==inf)ans=-1;

printf("%d\n",ans);

}

演算法課習題證明

吝嗇sat問題是這樣的 給定一組子句 每個子句都是其中文字的析取 和整數k,求乙個最多有k個變數為true的滿足賦值 如果該賦值存在。證明吝嗇sat是np 完全問題。假設有子句 a b c a b b c a c a b c 求a,b,c的取值 true or false 使得該表示式的結果是tru...

B 習題課一

計算導論與程式設計課程要開習題課,由於教室座位有限,所以決定限制參加人數。於是規定 1 最多允許一半的班級裡的同學參加 2 可以參加的班級最多允許一半的同學參加。現請你寫一段程式來計算習題課最多可能有多少個學生參加。輸入為兩行,第一行為乙個整數n 0題課的人數的最大值。當數字為奇數時,一半指的是該數...

B 習題課一

計算導論與程式設計課程要開習題課,由於教室座位有限,所以決定限制參加人數。於是規定 1 最多允許一半的班級裡的同學參加 2 可以參加的班級最多允許一半的同學參加。現請你寫一段程式來計算習題課最多可能有多少個學生參加。輸入為兩行,第一行為乙個整數n 0題課的人數的最大值。當數字為奇數時,一半指的是該數...