【HDU】5936 Difference 折半列舉
阿新 • • 發佈:2020-10-09
題意
定義函式\(f(y,k)=\sum_{i 是y的每一位}i^k\),比如\(f(232,2)=2^2+3^2+2^2==22\)。
\[x=f(y,k)-y \]現在給出 x 和 k,問有多少個 y 滿足上述式子。
思路
剛做了HDU 5735 ,有點經驗了。
對於一個整數 y,我們分為前 5 位和後 5 位。
那麼
\[\begin{aligned} &f(y,k)-y\\ &=(f(a,k)+f(b,k))-(a*100000+b)\\ &=(f(a,k)-a*100000)+(f(b,k)-b)\\ \end{aligned} \]那麼我們可以求出上面兩個括號內的所有值。
然後列舉其中一個值,二分另一個值。
注意 y 的值大於0,所以兩個式子不能同時為0,其實也就是特判一下 x==0的時候。
程式碼
/* * @Autor: valk * @Date: 2020-08-11 12:38:37 * @LastEditTime: 2020-10-09 10:16:49 * @Description: 如果邪惡 是華麗殘酷的樂章 它的終場 我會親手寫上 晨曦的光 風乾最後一行憂傷 黑色的墨 染上安詳 */ #include <algorithm> #include <iostream> #include <map> #include <math.h> #include <queue> #include <set> #include <stack> #include <stdio.h> #include <string.h> #include <string> #include <vector> #define pb push_back using namespace std; typedef long long ll; typedef unsigned long long ull; const int mod = 1e9 + 7; const int seed = 12289; const double eps = 1e-6; const int inf = 0x3f3f3f3f; const int N = 1e5 + 10; // vector<ll> vec1, vec2; ll qpow(ll a, ll b) { ll ans = 1; while (b) { if (b % 2) ans *= a; a *= a; b /= 2; } return ans; } int main() { ll T, cas = 0; scanf("%lld", &T); while (T--) { vec1.clear(), vec2.clear(); ll x, k; scanf("%lld%lld", &x, &k); for (ll i = 0; i <= 99999; i++) { ll temp = i; ll sum1 = 0; while (temp) { sum1 += qpow(temp % 10, k); temp /= 10; } vec1.pb(sum1 - i), vec2.pb(sum1 - i * 100000); } sort(vec2.begin(), vec2.end()); ll ans = 0; for (ll i = 0; i < vec1.size(); i++) { ll l = lower_bound(vec2.begin(), vec2.end(), x - vec1[i]) - vec2.begin(); ll r = upper_bound(vec2.begin(), vec2.end(), x - vec1[i]) - vec2.begin(); ans += r - l; } if(x==0){ ans--; } printf("Case #%lld: %lld\n", ++cas, ans); } return 0; }