codeforces心得1---747div2
cf div2的前AB題一般是字串or數論的找規律結論題
因此標程極為精簡
1.小竅門是看樣例或者自己打表或造資料找規律
2.一些不確定的操作,可以化成一種確定合法的操作比如:
div747 A的選擇l 和 r的操作,這裡的解是不確定的多個的,因此選擇簡單的且必然l加到r可以等於n的數,可以從數軸想到該數n>0時從l=1-n,r=n,n-1加到 1-n滿足為0 總和為n,而n<0時l=n,r=-n-1,從n+1 到 -n-1為0, 總和為n
div747C題,發現b<a 時a/b除不盡,於是最多兩次可以達到將字串轉換為某個特定字元的,選擇n,選擇n-1 ,(n/(n-1)除的盡在本題資料3≤n的範圍內不可行)
而字串裡面可能已經存在需要的字元,設位置為i,i之前的所有字元都會變成c(題目需要變成的字元),當i>x/2的時候,2>x/i>1,則x不能整除i,且比x小的都不能,所以讓i>n/2,就可以將所有的都變成c
3.即使發現了相同的規律,實現的程式碼的時候可以更加精練
div747B題,列數字可以看出,序列是n^0 n^1 n0+n1 n^2......
很像二進位制的 0001 0010 0011 0100,正好對應該數是升序第幾個,於是將k按照狀態壓縮,一位位取值然後相加
不過起始值是1,每過一位*n
精簡前
#include <bits/stdc++.h>
#define MOD (int)(1e9 + 7)
using namespace std;
long long a[105], rec[105];
int n, k;
int cal()
{
int chu = k, shang, yu = 0;
do
{
shang = chu / 2;
rec[++yu] = chu % 2;
chu = shang;
} while (shang);
return yu;
}
int main()
{
int t;
cin >> t;
while (t--)
{
cin >> n >> k;
int countn = cal();
long long sum = 0;
a[1] = 1;
for (int i = 2; i <= 35; i++)
{
a[i] = (a[i - 1] % MOD * n % MOD);
// cout << a[i] << endl;
}
for (int i = 1; i <= countn; i++)
{
if (rec[i])
{
sum += a[i];
sum %= MOD;
}
}
cout << sum << endl;
}
return 0;
}
精簡後
#include <bits/stdc++.h>
#define MOD (int)(1e9 + 7)
using namespace std;
int main()
{
int n, k, t;
cin >> t;
while (t--)
{
cin >> n >> k;
long long sum = 0, now = 1;
while (k)
{
if (k & 1)
{
sum = (sum + now) % MOD;
}
k >>= 1;
now = (now * n) % MOD;
}
cout << sum << endl;
}
return 0;
}