題目描述:
本題思路:
這道題,暴力過30%的樣例,拿的了7分的樣子,要全過的話那得dp,寫數學式子分析,找到盡可能減少複雜度的方法。
先上暴力**(這道題暴力寫應該很容易的):
#include
using
namespace std;
const
int n =
1e5+10;
typedef
long
long ll;
int n, k;
int a[n]
;int
main()
for(
int i =
0; i < n -
1; i++
)int lenx =
log10
(x)+1;
int leny =
log10
(y)+1;
ll nowx = y *
pow(
10, lenx)
+ x;
ll nowy = x *
pow(
10, leny)
+ y;if(
!(nowx % k))if
(!(nowy % k))}
} cout << cnt << endl;
return0;
}
數學分析:
判斷兩個數的拼接是否能被k整除,假設當前運算元為a[i], a[j]。
拼接之後的數就是a[i]*10^(log10a[j]) + a[j],對k取模,式子就是(a[i]*10 ^ (log10a[j] + 1) % k + a[j] % k)% k,這個式子的範圍在0~10 ^ 5之間,我們對這個式子進行分解分析:
第一部分:a[ i ] * 10 ^ (log10a[j] + 1) % k,其實就可以算出a[i]乘以不同的冪對k取模值為前面那個式子的個數,即用dp[冪][a[i]*10^(log10a[j]) % k]記錄個數
第二部分:a[j] % k,就可以根據上面得到的個數直接找到k - a[j] % k有多少個,這兩項之和可以被k整除,因為a[j] % k 可能為0,所以就再取一次模,(k - a[j] % k)% k.
然後在遍歷的時候直接累加到ans裡面就行
**部分solve()函式解決的就是記錄個數的部分,但是因為是在計數部分進行ans的更新的,所以ans記錄的只有當前某個運算元a[i]之前拼接的個數。
所以我們還得反向進行一次計算,即直接把陣列a翻轉一下,mst一下cnt,再跑一遍solve()即可。
最後輸出ans就可以啦~
**部分:
#include
#define mst(a, n) memset(a, n, sizeof(a))
using
namespace std;
typedef
long
long ll;
const
int n =
1e5+10;
int a[n]
;int cnt[11]
[n];
//cnt[i][j]表示i次冪下模k後值為j的個數
int n, k;
ll ans;
void
solve()
}}intmain()
solve()
;//拼接a[j][i]
mst(cnt,0)
;reverse
(a, a + n)
;solve()
;//拼接a[i]a[j]
cout << ans << endl;
return0;
}
2020第十一屆藍橋杯7月省賽J題
題目描述 本題思路 這道題是乙個帶權並查集,當初一看到這個題目的時候應該就要想到並查集,因為有權值的存在,所以我們可以想到帶權並查集。我們如果普通維護當前結點與父結點之間的關係的話,很明顯非常難維護,但是如果我們維護當前結點與祖先結點之間的關係的話,那就會好很多,我們每次把更新操作都在祖先結點上面做...
第十一屆藍橋杯
問題描述 小藍要為一條街的住戶製作門牌號。這條街一共有 2020 位住戶,門牌號從 1 到 2020 編號。小藍製作門牌的方法是先製作 0 到 9 這幾個數字字元,最後根據需要將字 符貼上到門牌上,例如門牌 1017 需要依次貼上字元 1 0 1 7,即需要 1 個 字元 0,2 個字元 1,1 個...
第十一屆藍橋杯省賽 走方格
時間限制 1.0s 記憶體限制 512.0mb 本題總分 20 分 問題描述 在平面上有一些二維的點陣。這些點的編號就像二維陣列的編號一樣,從上到下依次為第 1 至第 n 行,從左到右依次為第 1 至第 m 列,每乙個點可以用行號和列號來表示。現在有個人站在第 1 行第 1 列,要走到第 n 行第 ...