1. 程式人生 > >哈爾濱理工大學軟體與微電子學院第八屆程式設計競賽同步賽(高年級) A 小樂樂的組合數+ 【規律】

哈爾濱理工大學軟體與微電子學院第八屆程式設計競賽同步賽(高年級) A 小樂樂的組合數+ 【規律】

任意門:https://ac.nowcoder.com/acm/contest/301/A

題意概括:

連結:https://ac.nowcoder.com/acm/contest/301/A
來源:牛客網

小樂樂得知一週有7天之後就對7產生了興趣。 小樂樂得到了兩堆數字數字時連續的。 第一堆包含[1,n]n個數字,第二堆包含[1,m]m個數字。
小樂樂想要從兩堆中各挑選出一個整數x,y,使得x,y的和為7的倍數。

請問小樂樂有多少種組合的方式。

 

解題思路:

一開始想 O(1) 解決查詢。

在一個特殊情況 卡 了:

輸入N M 調整使得 N < M

那麼我們其實就是遍歷 N 來得出最後的結果。

很明顯 只要滿足了 給第 i 個數 (7 - i % 7)那麼剩下有多少個七就說明 i 有多少種可能

然後把 i 累加起來最後得到的答案 就是 最後的方案數了。

 

然而天真的我想要 簡化這條式子 最後傻傻的簡化成了 ans = N*M - N + (N/7)+N%7;

這條式子 bug 在了處理 m 等於 8 這種邊界值的情況,並沒有把遞推的性質完全繼承下來。

而這道題一個for迴圈遍歷 N 求和 是在複雜度範圍之內的,對複雜度的估算有誤。

最後找出了遞推式,一次遍歷,搞定。

果然,比賽才是王道,賽時打了表,找了個規律,wa,心態爆炸 太久沒打dp 以至於一開始 E 題很明顯的最長公共子序列都卡死了,

賽後冷靜下來,硬生生地把遞推式弄出來。

那些挖了的坑沒有填,現在成功把自己坑了,dp,搜尋怎麼能丟呢。

 

AC code:

 1 #include <cstdio>
 2 #include <iostream>
 3 #include <cstring>
 4 #include <algorithm>
 5 #include <cmath>
 6 #include <map>
 7 #define INF 0x3f3f3f3f
 8 #define LL long long
 9 using
namespace std; 10 11 LL N, M; 12 13 LL inv(LL x, LL p) 14 { 15 LL res = 1LL; 16 while(p){ 17 if(p&1LL) res*=x%7LL; 18 x*=x; 19 p>>=1; 20 } 21 return res; 22 } 23 int main() 24 { 25 while(~scanf("%lld %lld", &N, &M)){ 26 LL ans = 0LL; 27 if(N > M) swap(N, M); 28 if(M < 7LL){ 29 ans = 0; 30 for(LL i = 1LL; i <= N; i++) 31 if(M >= (7LL-i)) ans++; 32 } 33 else{ 34 // ans = (N*M)-7*N; 35 // ans = ans + 21*(N/7); 36 // if(N > 7) 37 // for(int i = 1; i <= N%7; i++) 38 // ans+=i; 39 // ans = ans/7 + N; 40 ans = N; 41 for(LL i = 1LL; i <= N; i++){ 42 ans += (M-(7LL-i%7))/7LL; 43 } 44 } 45 printf("%lld\n", ans); 46 } 47 return 0; 48 }