題目給出兩個(gè)數(shù)字a, b, 讓你求出 a - b 范圍內(nèi)每個(gè)數(shù)字”圈“的總和。 對(duì)于這樣的區(qū)間和問(wèn)題,直接預(yù)處理出前綴和。查詢即可
`#includeusing namespace std;
const int N = 1e6 + 10;
int cir[10] = {1, 0, 0, 0, 1, 0, 1, 0, 2, 1};
int f[N];
int main()
{int n;
cin >>n;
//根據(jù)數(shù)據(jù)范圍,預(yù)處理出 1 - 1e6 的前綴和數(shù)組
for(int i = 1; i<= 1000000; i++)
{int x = i;
int sum = 0;
while(x)
{sum += cir[x % 10];
x /= 10;
}
f[i] += f[i - 1] + sum;
}
for(int i = 0; i< n; i++)
{int a, b;
cin >>a >>b;
cout<< f[b] - f[a - 1]<< endl;
}
return 0;
}
2.題目:珂朵莉與宇宙
題目鏈接:珂朵莉與宇宙
解題思路:假設(shè)暴力處理,那么需要枚舉所有的子區(qū)間內(nèi)的和,枚舉區(qū)間和用前綴和,并枚舉理論上符合的 j^2。
即為, s[r] - s[l] = j^2,枚舉三個(gè)變量肯定超時(shí)。
通過(guò)變化式子
s[r] - j^2 = s[l], 那么只需要枚舉 r, 和 j, 和符合的 s[l], 的個(gè)數(shù),因?yàn)閟[l], 可以循環(huán) r 時(shí),一并維護(hù)出,所以優(yōu)化掉一個(gè)枚舉。
#include#include
3.題目:激光炸彈
題目鏈接:激光炸彈
解題思路:二維前綴和,因?yàn)槲覀円杜e很多子區(qū)間,觀察數(shù)據(jù)范圍,如果枚舉子區(qū)間會(huì)超時(shí)。對(duì)于二維區(qū)間和的問(wèn)題,我們使用二維前綴和。
不會(huì)二維前綴和可以參考以下文章
二維前綴和
#includeusing namespace std;
const int N = 5010;
int g[N][N];
int main()
{ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
int n, m;
cin >>n >>m;
for(int i = 0; i< n; i++)
{int a, b, c;
cin >>a >>b >>c;
a++, b++;
g[a][b] = c;
}
for(int i = 1; i< N; i++)
for(int j = 1; j< N; j++)
{g[i][j] = g[i - 1][j] + g[i][j - 1] - g[i - 1][j - 1] + g[i][j];
}
int ans = 0;
for(int i = m; i< N; i++)
for(int j = m; j< N; j++)
{int x2 = i, y2 = j;
int x1 = i - m + 1, y1 = j - m + 1;
ans = max(ans, g[x2][y2] - g[x1 - 1][y2] - g[x2][y1 - 1] + g[x1 - 1][y1 - 1]);
}
cout<< ans;
return 0;
}
二:差分
1.題目:校門外的樹(shù)
題目鏈接:校門外的樹(shù)
解題思路:首先觀察數(shù)據(jù)范圍,考慮暴力是否可做,可做,這里不提供暴力解法。
這個(gè)題推薦使用差分來(lái)做,來(lái)練習(xí)差分的使用。
差分可以實(shí)現(xiàn)對(duì)一個(gè)區(qū)間的所有數(shù),加減一個(gè)數(shù)字。對(duì)此題,我們假設(shè) 0 代表有樹(shù)木,對(duì)一段區(qū)間砍樹(shù)就規(guī)定為對(duì)一段區(qū)間的數(shù) -1。
這樣我們就減少了去遍歷區(qū)間內(nèi)的每個(gè)數(shù)字進(jìn)行減法,而在最后所有操作進(jìn)行完畢之后,統(tǒng)一計(jì)算每個(gè)點(diǎn)的值。如果還是0,那么還有樹(shù)。
#includeusing namespace std;
const int N=1e4 + 10;
int f[N];
int n, m;
int main()
{cin >>n >>m;
for(int i = 0; i< m; i++)
{int a, b;
cin >>a >>b;
f[a]--;
f[b + 1]++;
}
int ans = 0;
for(int i = 0; i<= n; i++)
{f[i] += f[i - 1];
if(!f[i]) ans++;
}
cout<< ans<< endl;
return 0;
}
2.題目:貨物種類
題目鏈接:貨物種類
解題思路:不難發(fā)現(xiàn)這個(gè)不同于以前的統(tǒng)計(jì)個(gè)數(shù)嗎,而是統(tǒng)計(jì)不同種類的數(shù)量。所以我們不能對(duì)個(gè)數(shù)進(jìn)行維護(hù)差分?jǐn)?shù)組。
所以我們要對(duì)不同的種類維護(hù)差分?jǐn)?shù)組,所以我們需要一個(gè)一個(gè)種類的進(jìn)行加。并且重復(fù)區(qū)間不能重復(fù)計(jì)數(shù),需要區(qū)間合并。
所以我們先結(jié)構(gòu)體存下來(lái),進(jìn)行排序。
因?yàn)槲覀円M(jìn)行區(qū)間合并,所以盡可能 l 的小的排在前面。
區(qū)間合并時(shí):分三種情況。
對(duì)于同一個(gè)種類的區(qū)間合并:
1.如果說(shuō)下一個(gè)區(qū)間的 l 大于當(dāng)前維護(hù)的區(qū)間的 r, 說(shuō)明這倆區(qū)間沒(méi)有交集,那么 維護(hù)區(qū)間數(shù)組,更新維護(hù)的區(qū)間
2.否則當(dāng)前l(fā) 小于等于當(dāng)前維護(hù)區(qū)間的 r,說(shuō)明他倆有交集,如果說(shuō)當(dāng)前 r >當(dāng)前維護(hù)的區(qū)間,那么維護(hù)區(qū)間 r 需要擴(kuò)大了。
遇到不同種類了
把之前維護(hù)的區(qū)間更新差分?jǐn)?shù)組,然后更新區(qū)間
#includeusing namespace std;
const int N = 1e5 + 10;
int f[N];
struct Node
{int l, r, id;
}e[N];
bool bmp(Node x, Node y)
{if(x.id != y.id)
return x.id< y.id;
else if(x.l != y.l)return x.l< y.l;
else return x.r< y.r;
}
int main()
{int n, m;
cin >>n >>m;
for(int i = 1; i<= m; i++) cin >>e[i].l >>e[i].r >>e[i].id;
sort(e + 1, e + m + 1, bmp);
int st = e[1].l, ed = e[1].r;
int last = e[1].id;
for(int i = 2; i<= m; i++)
{if(last != e[i].id)
{last = e[i].id;
f[st]++, f[ed + 1]--;
st = e[i].l, ed = e[i].r;
}else
{if(e[i].l >ed)
{f[st]++, f[ed + 1]--;
st = e[i].l, ed = e[i].r;
}else if(ed< e[i].r) ed = e[i].r;
}
}
f[st]++, f[ed + 1]--;
int mxx = 0;
int ans = 0;
for(int i = 1; i<= n; i++)
{f[i] += f[i - 1];
if(f[i] >mxx)
{mxx = f[i];
ans = i;
}
}
cout<< ans<< endl;
return 0;
}
3.題目:放學(xué)后茶會(huì)的甜點(diǎn)
題目鏈接:[放學(xué)后茶會(huì)的甜點(diǎn)]
解題思路:優(yōu)先學(xué)習(xí)二維差分:
二維差分
二維差分預(yù)處理題目對(duì)子區(qū)間增加 1。題目問(wèn)取任意大小的區(qū)間的大平均甜度,既然是平均甜度,所以我們?nèi)〈笾的且粋€(gè)即可。
因?yàn)槠骄挡粫?huì)超過(guò)大值。
#includeusing namespace std;
const int N = 1010;
int g[N][N];
int main()
{int n, m, t;
cin >>n >>m >>t;
for(int i = 1; i<= t; i++)
{int x1, y1, x2, y2;
cin >>x1 >>y1 >>x2 >>y2;
g[x1][y1] += 1;
g[x2 + 1][y1] -= 1;
g[x1][y2 + 1] -= 1;
g[x2 + 1][y2 + 1] += 1;
}
int ans = 0 ;
for(int i = 1; i<= n; i++)
for(int j = 1; j<= m; j++)
{g[i][j] += g[i - 1][j] + g[i][j - 1] - g[i - 1][j - 1];
ans = max(ans, g[i][j]);
}
cout<< ans<
三:貪心
1.題目:小杰的簽到題
題目鏈接:小杰的簽到題
解題思路:首先不希望桌子有空閑時(shí)間,所以誰(shuí)先到誰(shuí)就先排隊(duì)。
所以我們先排序所有人的到達(dá)時(shí)間,從到達(dá)時(shí)間小的開(kāi)始放置。
假設(shè)對(duì)于我們當(dāng)前要放置的隊(duì)伍來(lái)說(shuō),肯定放在最先結(jié)束的桌子上。找到三個(gè)桌子誰(shuí)先結(jié)束。所以我們需要維護(hù)每個(gè)桌子當(dāng)前結(jié)束時(shí)間。
void solved()
{cin >>n;
for(int i = 0; i< n; i++) cin >>a[i];
cin >>m;
//初始化桌子,時(shí)間都?xì)w0
for(int i = 0 ;i< 3; i++)
que[i] = 0;
//排序讓先到的進(jìn)行
sort(a, a + n);
for(int i = 0; i< n; i++)
{int x = a[i];
int mnn = 1e9; // 找到三個(gè)桌子誰(shuí)最先結(jié)束
int xb = 0; //記錄是第幾個(gè)桌子
for(int j = 0; j< 3; j++)
{if(que[j]< mnn) mnn = que[j], xb = j;
}
//如果說(shuō)當(dāng)前隊(duì)伍大于等于最先結(jié)束的了,那么肯定按照當(dāng)前隊(duì)伍到達(dá)的時(shí)間來(lái)開(kāi)始
if(x >= mnn)
{que[xb] = x + m;
}else que[xb] = mnn + m;
//如果我們到達(dá)的時(shí)候還沒(méi)有空桌子,那么肯定等空桌子結(jié)束我們開(kāi)始
}
//三個(gè)桌子找到最晚結(jié)束的就是我們的答案
int ans = 0;
for(int i = 0; i< 3; i++)
{ans = max(ans, que[i]);
}
cout<< ans<< endl;
}
2.題目:排座椅
題目鏈接:排座椅
解題思路:首先題目中說(shuō)所有說(shuō)話的人是相鄰的(上下左右), 對(duì)于豎著相鄰的人來(lái)說(shuō),橫著的過(guò)道才能影響,對(duì)于橫著相鄰的來(lái)說(shuō),豎著的過(guò)道影響。
對(duì)于一條豎著的過(guò)道,影響的只能是相鄰兩列的人,所以貪心的來(lái)說(shuō),對(duì)于每一條過(guò)道我們都希望是影響最多的人。
那么統(tǒng)計(jì)一下每對(duì)人如果要拆開(kāi),需要在哪一列 / 一行,防止過(guò)道。然后排序從大到小,輸出題目要求的過(guò)道數(shù)量即可。
需要注意的點(diǎn),題目要求輸出過(guò)道的位置時(shí),要求從小到大輸出。
因?yàn)槲覀冃枰敵瞿膫€(gè)過(guò)道被統(tǒng)計(jì)的數(shù)量最多,所以我們?cè)诮y(tǒng)計(jì)次數(shù)的時(shí)候,也要標(biāo)記上是哪個(gè)過(guò)道,這樣排序的時(shí)候我們知道是哪個(gè)過(guò)道最多。
所以使用結(jié)構(gòu)體存。
#includeusing namespace std;
const int N = 2010;
int hs[N], ls[N];
struct Node
{int id, w;
}he[N], le[N]; //分別統(tǒng)計(jì)行和列的次數(shù)
bool bmp(Node x, Node y)
{return x.w >y.w;
}
int main()
{int n, m, k, l, d;
cin >>n >>m >>k >>l >>d;
for(int i = 0; i< d; i++)
{int x1, y1, x2, y2;
cin >>x1 >>y1 >>x2 >>y2;
//上下相鄰
if(x1 == x2)
{he[min(y1, y2)].w++;
he[min(y1, y2)].id = min(y1, y2); //避免排序時(shí)候不知道是哪個(gè)過(guò)道
}else if(y1 == y2) //左右相鄰
{le[min(x1, x2)].w++;
le[min(x1, x2)].id = min(x1, x2);
}
}
//按照統(tǒng)計(jì)次數(shù),從大到小
sort(he, he + N, bmp), sort(le, le + N, bmp);
//因?yàn)轭}目要求輸出的時(shí)候按照 過(guò)道的下標(biāo)從小到大
vectorans1, ans2;
for(int i = 0; i< k; i++)
ans1.push_back(le[i].id);
for(int i = 0; i< l; i++)
ans2.push_back(he[i].id);
sort(ans1.begin(), ans1.end()), sort(ans2.begin(), ans2.end());
for(int i = 0; i< ans1.size(); i++)
cout<< ans1[i]<< " ";
cout<< endl;
for(int j = 0; j< ans2.size(); j++)
cout<< ans2[j]<< " ";
return 0;
}
3.題目:紀(jì)念品分組
題目鏈接:紀(jì)念品分組
解題思路:題目規(guī)定,最多 2 個(gè)物品一組,并且組內(nèi)大物品不能超過(guò)上限值,問(wèn)你最少多少組。
我們肯定希望盡可能滿足 2 個(gè)物品一組,所以我們讓最小的價(jià)值和大的價(jià)值組一塊是最優(yōu)解。如果說(shuō)不能組一塊,那大價(jià)值只能自己一組。
那么最小值就依次找次小值。
#includeusing namespace std;
const int N = 30010;
int n, m;
int a[N];
int main()
{cin >>m >>n;
for(int i = 0; i< n; i++) cin >>a[i];
sort(a, a + n);
int l = 0;
int ans = 0;
for(int i = n - 1; i >= l; i--)
{if(i == l)
{ans++;
break;
}
if(a[i] >= m) ans++;
else
{if(a[i] + a[l] >m)
{ans++;
}else
{ans++;
l++;
}
}
}
cout<< ans;
return 0;
}
4.題目:巨石滾滾
題目鏈接:巨石滾滾
解題思路:需要注意的點(diǎn),土球會(huì)先撞,再回復(fù),如果說(shuō)撞的時(shí)候就< 0, 那么就失敗了。
首先我們可以把所有的障礙分為兩類,一類是撞完會(huì)增加的,另一類是撞完會(huì)減少的。
因?yàn)槲覀兿MM可能的把球的穩(wěn)定性變成大,然后再減小,這樣盡可能滿足更多的障礙。
所以我們先撞增加的,再撞減小的。
對(duì)于先撞增加的這一類:
因?yàn)橄茸苍僭黾樱员M可能的使得撞的值小的放在前面,讓球的穩(wěn)定性盡可能大,避免撞完就小于0。
可能會(huì)說(shuō),存在一個(gè)增加的障礙,但是他的損耗是很大的,肯定會(huì)導(dǎo)致撞完就小于0,不能回復(fù)。
這樣因?yàn)樗亲餐暝黾拥模覀儼阉旁谇懊妫遣皇亲顑?yōu)解?。
因?yàn)槲覀兊囊笫悄軌虻竭_(dá)終點(diǎn),而不是通過(guò)最多的障礙。
因?yàn)檫@個(gè)是損耗大的回復(fù),所以我們肯定把他放在這一類的最后來(lái)撞,因?yàn)檫@時(shí)已經(jīng)是極大值的穩(wěn)定性,如果這時(shí)都不能通過(guò),所以肯定不能到達(dá)終點(diǎn)。
對(duì)于撞完損耗這一類:
因?yàn)槲覀兡繕?biāo)是到重點(diǎn),那么如果到終點(diǎn),我們大值 + 回復(fù) 一定大于所有的損耗 (損耗是一個(gè)定值),否則肯定會(huì)在路上失敗。
那么我們盡可能的讓回復(fù)多的在前面,這樣就盡可能的滿足穩(wěn)定性大。
#includeusing namespace std;
typedef pairPII; //typedef 同define, pair用法 csdn搜索
#define x first
#define y second
const int N = 500010;
int n, m;
bool bmp1(PII a, PII b)
{return a.x< b.x;
}
bool bmp2(PII a, PII b)
{return a.y >b.y;
}
PII all[N];
void solved()
{cin >>n >>m;
vectorzh, fu;
for(int i = 0; i< n; i++)
{cin >>all[i].x >>all[i].y;
if(all[i].y - all[i].x >= 0) zh.push_back(all[i]);
else fu.push_back(all[i]);
}
sort(zh.begin(), zh.end(), bmp1);
sort(fu.begin(), fu.end(), bmp2);
long long sum = m;
for(int i = 0; i< zh.size(); i++)
{if(sum - zh[i].x< 0)
{cout<< "No"<< endl;
return;
}else sum -= zh[i].x, sum += zh[i].y;
}
for(int i = 0; i< fu.size(); i++)
{if(sum - fu[i].x< 0)
{cout<< "No"<< endl;
return;
}else sum -= fu[i].x, sum += fu[i].y;
}
cout<< "Yes"<< endl;
}
int main()
{int T;
cin >>T;
while(T--) solved();
return 0;
}
四:二分&二分答案
1.題目:.完全平方數(shù)
題目鏈接:完全平方數(shù)
解題思路:暴力的解法就是 從 左區(qū)間l到右區(qū)間r 找到滿足條件數(shù)的個(gè)數(shù)。但考慮到 l和r的大小 可以先預(yù)處理出來(lái)所有的平方數(shù),然后用二分查找到 處于區(qū)間(l,r)滿足條件數(shù)的范圍。即 查找 l和r所在預(yù)處理數(shù)組中的位置。
代碼塊:#include#includeusing namespace std;
#define ll long long
vectorv;
void solve(){ll l1,r1;cin>>l1>>r1;
ll l=0,r=v.size()-1;
ll k1=-1;
ll k2=-1;
//找到第一個(gè) 大于等于 l1的
while(lll mid=(l+r)>>1;
if(v[mid]>=l1)r=mid;
else l=mid+1;
}
k1=l;
//找到最后一個(gè) 小于等于r1的
l=0,r=v.size()-1;
while(lll mid=(l+r+1)>>1;
if(v[mid]<=r1)l=mid;
else r=mid-1;
}
k2=l;
cout<for(ll i=0;i*i<=1e9;i++){v.push_back(i*i);
}
ll t;cin>>t;
while(t--)solve();
}
2.題目:解方程
題目鏈接:解方程
解題思路:可以使用二分答案 枚舉區(qū)間(0,100)內(nèi)的所有數(shù)字,注意寫好check函數(shù)就可以了。這里可以學(xué)習(xí)經(jīng)典 浮點(diǎn)數(shù)二分的處理方法。
代碼塊:#include#include#define ll long long
using namespace std;
double n;
double check(double m){ double s=m*m*m*m*2018+m*21+5*m*m*m+5*m*m+14;
return s;
}
void solve(){cin>>n;
if(check(100)cout<<"-1"<0.00001){double mid=(l+r)/2.0;
if(check(mid)>=n)r=mid;
else l=mid+0.00000001;
}
printf("%.4f\n",l);
}
int main(){ll t;cin>>t;
while(t--){solve();
}
return 0;
}
3.題目:跳石頭
題目鏈接:跳石頭
解題思路:使用二分答案,通過(guò)枚舉 答案 即最短跳躍距離的大值,check()函數(shù)是判斷該答案是否可行,是通過(guò) 計(jì)算 在滿足該條件下需要移走巖石的個(gè)數(shù),是否滿足題目限制的大移動(dòng)巖石個(gè)數(shù)。
代碼塊:#include#include#include#include
#include#include#include#include#define ll long long
const double eps = 1e-4;
ll gcd(ll a, ll b) {return b ? gcd(b, a % b) : a; }//最小公約數(shù)__gcd()
using namespace std;
const int NX=1e5+10;
ll x[NX];
ll y[NX];
ll L, N, M;
bool check(ll k)
{ll sum = 0;
for (int i = 1; i<= N; i++)
{ll j = i - 1;
while (y[j] != 0)j--;
if ((x[i] - x[j])sum++;
y[i] = 1;
if (sum >M)return false;
}
}
ll s = N;
while (y[s] != 0)s--;
if ((x[N + 1] - x[s])< k)sum++;
if (sum >M) return false;
else return true;
}
int main()
{cin >>L >>N >>M;
for (int i = 1; i<= N; i++)
{cin >>x[i];
}
x[0] = 0;
x[N + 1] = L;
ll l = 0;
ll r = 1e9+10;
while (l< r)
{memset(y, 0, sizeof(y));
ll mid = (l + r) >>1;
if (check(mid))l =mid+1;
else r = mid;
}
cout<< l-1<< endl;
return 0;
}
4.題目:借教室
題目鏈接:[借教室]
解題思路:該題目 相當(dāng)于是 跳石頭 的一個(gè)拓展,同樣是枚舉答案 需要通知哪個(gè)申請(qǐng)人修改訂單。注意check()函數(shù)的書(shū)寫,在判斷答案 是否可行的時(shí)候 需要用到 一點(diǎn)差分的知識(shí)。 使用差分處理完該申請(qǐng)人 之前的所有訂單,然后看是否有不符合要求的情況,即供不應(yīng)求(需要的教室個(gè)數(shù) 大于 有空閑的教室個(gè)數(shù)。
代碼塊:#include#include#includeusing namespace std;
#define ll long long
const int N=1e6+10;
ll n,m;
ll a[N],b[N],c[N],d[N],e[N]={0};
bool check(int k)
{memset(e,0,sizeof(e));
for(int i=1;i<=k;i++)
{ e[c[i]]+=b[i];
e[d[i]+1]-=b[i];
}
for(int i=1;i<=n;i++)
{e[i]+=e[i-1];
if(e[i]>a[i])return false;
}
return true;
}
int main()
{cin>>n>>m;
for(int i=1;i<=n;i++)cin>>a[i];
for(int i=1;i<=m;i++)cin>>b[i]>>c[i]>>d[i];
ll l=1,r=m;
while(l ll mid=(l+r)>>1;
if(check(mid))l=mid+1;
else r=mid;
}
if (l != m){cout<<"-1"<
五:雙指針?biāo)惴?
1.題目:滑動(dòng)窗口
題目鏈接:滑動(dòng)窗口
解題思路:雙指針經(jīng)典用法,需要 用兩個(gè)指針維護(hù)一個(gè)窗口的長(zhǎng)度,然后不停的在一個(gè)數(shù)組上滑動(dòng)。首先 需要注意,兩個(gè)指針必須一起移動(dòng),并且 該窗口的長(zhǎng)度不會(huì)改變,所以 可以使用 滑動(dòng)窗口去 維護(hù) 給定區(qū)間長(zhǎng)度 的最值。
代碼塊:#include#include
#include#include#include#include
2.題目:逆序數(shù)(歸并排序)
題目鏈接:[逆序數(shù)]
解題思路:首先我們知道逆序數(shù)的定義,然后發(fā)現(xiàn)通過(guò) 歸并排序 的過(guò)程,可以計(jì)算逆序數(shù),然后 歸并排序 其實(shí)就是通過(guò)遞歸 在回溯的過(guò)程中(通過(guò)定義 發(fā)現(xiàn) 回溯過(guò)程返回的都是 有序數(shù)組),,使用 雙指針 有序合并兩個(gè)有序數(shù)組。
代碼塊:#includeusing namespace std;
#define ll long long
const int N=1e5+10;
ll q[N],tmp[N];
ll ans=0;
void merge_sort(ll q[], ll l, ll r)
{if (l >= r) return;
ll mid =( l + r) >>1;
merge_sort(q, l, mid);
merge_sort(q, mid + 1, r);
ll k = 0, i = l, j = mid + 1;
while (i<= mid && j<= r)
if (q[i]<= q[j]) tmp[k ++ ] = q[i ++ ];
else {tmp[k ++ ] = q[j ++ ];ans+=mid-i+1;}
while (i<= mid) tmp[k ++ ] = q[i ++ ];
while (j<= r) tmp[k ++ ] = q[j ++ ];
for (i = l, j = 0; i<= r; i ++, j ++ ) q[i] = tmp[j];
}
int main(){ll n;cin>>n;
for(int i=1;i<=n;i++)cin>>q[i];
merge_sort(q, 1, n);
cout<
六:遞歸&分治
1.題目:數(shù)的計(jì)算
題目鏈接:數(shù)的計(jì)算
解題思路:首先使用暴力 可以發(fā)現(xiàn)f(i)=f(1)+f(2)+…+f(i/2)然后寫一個(gè)遞歸函數(shù)就可以
但是 發(fā)現(xiàn)題目數(shù)據(jù) 發(fā)現(xiàn)這樣 暴力過(guò)不了,因?yàn)?我們做了很多重復(fù)的計(jì)算,比如 當(dāng)i為奇數(shù)的時(shí)候 它能添加數(shù)字的情況跟(i-1)添加數(shù)字的情況一樣,當(dāng)i為偶數(shù)的時(shí)候,就相當(dāng)于在(i-1)的基礎(chǔ)上加上了 i可添加的自然數(shù)的情況,即(i/2)的情況一樣。得到普遍規(guī)律: 當(dāng)i為奇數(shù)的時(shí)候f(i)=f(i-1) 當(dāng)i為偶數(shù)的時(shí)候 f(i)=f(i-1)+f(i/2).
#includeusing namespace std;
#define ll long long
ll dfs(ll k){if(k==1)return 1;
if(k%2)return dfs(k-1);
else return dfs(k-1)+dfs(k/2);
}
int main(){ll n;cin>>n;
cout<< dfs(n)<
2.題目:小q的數(shù)列
題目鏈接:小q的數(shù)列
解題思路:題目有兩個(gè)要求,第一個(gè)要求 就可以直接通過(guò) 題目給出的條件進(jìn)行遞歸就可以,第二個(gè)條件 通過(guò)枚舉不難發(fā)現(xiàn)跟二進(jìn)制有關(guān)系,每次一個(gè)新數(shù)x的出現(xiàn)一定是在 2的x次方-1的位置出現(xiàn)。
代碼塊:#include#include#include
#include#define ll long long
using namespace std;
ll solve(ll n)
{if(n==0)return 0;
if(n==1)return 1;
return solve(n/2)+solve(n%2);
}
int main()
{ ll t;cin>>t;
while(t--)
{ll n;cin>>n;
ll a=solve(n);
ll p=pow(2,a)-1;
printf("%lld %lld\n",a,p);
}
return 0;
}
3.題目:求先序排列
題目鏈接:求先序排列
解題思路:我們首先 需要學(xué)習(xí) 樹(shù)的三種遍歷方式(本質(zhì)計(jì)算 對(duì)根節(jié)點(diǎn)的訪問(wèn)順序不同),先序排列(根左右) 中序排列(左根右)后序排列(左右根)先序排列的第一個(gè)是根節(jié)點(diǎn),后序排列的最后一個(gè)節(jié)點(diǎn)是根節(jié)點(diǎn)。我們可以先根據(jù)后序序列找到根節(jié)點(diǎn),然后根據(jù)這個(gè)根節(jié)點(diǎn)來(lái)對(duì)中序以及后序序列進(jìn)行分割,于是可以得到左右字?jǐn)?shù),然后對(duì)左子樹(shù)以及右子樹(shù)進(jìn)行遞歸地處理。
代碼塊:#include#includeusing namespace std;
#define ll long long
void solve(string s1,string s2){ll k1=s1.size();
ll k2=s2.size();
if(k2<=0)return;
cout<string s1,s2;cin>>s1>>s2;
solve(s1,s2);
return 0;
}
七:STL
1.題目:掃雷游戲
題目鏈接:掃雷游戲
解題思路:根據(jù)題意 如果該位置是非地雷格的時(shí)候 你需要 計(jì)算它周圍的地雷個(gè)數(shù),如果是地雷格的話 就直接輸出‘*’
這里有個(gè)小技巧 在地圖上 位置的遍歷可以用 x和y相對(duì)于原來(lái)位置數(shù)值的變化 直接判斷八個(gè)方向,在代碼中用 d_x和d_y實(shí)現(xiàn)。
#include#include#include
#include
2.題目:圖書(shū)管理員
題目鏈接:圖書(shū)管理員
解題思路:首先理解題意我們發(fā)現(xiàn)我們需要 找到是否能夠找到讀者需要的書(shū),找到的話輸出 圖書(shū)編碼最小的書(shū),反之輸出 -1,我們可以 先將圖書(shū)排序,然后每次進(jìn)行查詢的時(shí)候,就遍歷一遍 如果存在就輸出(因?yàn)橐呀?jīng)進(jìn)行了排序,所以能夠保證 每次最先找到的是圖書(shū)編碼最小的書(shū)),不存在就輸出-1.
代碼塊:#include#include#include
#include
你是否還在尋找穩(wěn)定的海外服務(wù)器提供商?創(chuàng)新互聯(lián)www.cdcxhl.cn海外機(jī)房具備T級(jí)流量清洗系統(tǒng)配攻擊溯源,準(zhǔn)確流量調(diào)度確保服務(wù)器高可用性,企業(yè)級(jí)服務(wù)器適合批量采購(gòu),新人活動(dòng)首月15元起,快前往官網(wǎng)查看詳情吧
網(wǎng)站名稱:寒假訓(xùn)練第一場(chǎng)-創(chuàng)新互聯(lián)
分享網(wǎng)址:http://www.chinadenli.net/article0/psgoo.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站建設(shè)、標(biāo)簽優(yōu)化、網(wǎng)頁(yè)設(shè)計(jì)公司、云服務(wù)器、App開(kāi)發(fā)、定制網(wǎng)站
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)
猜你還喜歡下面的內(nèi)容