地址:https://ac.nowcoder.com/acm/contest/8688/A
題意:
給出x,y,z,k的范圍a,b,c,d
求能組成多少種x+y+z=k
解析:
這是差分數組推導過程的入口:https://www.cnblogs.com/liyexin/p/11014218.html
考慮先枚舉a,得出所有的0~a+b的每個結果的數目。
然后在得知a+b的每個數目的情況下,再得到所有0~a+b+c的每個結果的數目。
實現過程,可以通過差分數組來實現。
先枚舉a,那么對於每個a,a+b的范圍在a~a+b之間,那么范圍內每個結果的數目都要+1,有:f[i]++,f[i+b+1]--
前綴和操作一下,還原數組。
同理,在f[]已知各個a+b的種類情況下,枚舉a+b,通過f[]來求0~a+b+c的每個出現次數
前綴和還原。
接下來把p[]加到d即可。
#include<iostream> #include<cmath> using namespace std; #include<map> typedef long long ll; const int maxn=1e8; ll f[maxn],p[maxn]; int main() { ll a,b,c,d; cin>>a>>b>>c>>d; for(int i=0;i<=a;i++) { f[i]++; f[i+b+1]--; } for(int i=0;i<=a+b;i++) f[i]+=f[i-1]; for(int i=0;i<=a+b;i++) { p[i]+=f[i]; p[i+c+1]-=f[i]; } for(int i=0;i<=a+b+c;i++) p[i]+=p[i-1]; ll all=0; for(int i=0;i<=d;i++) { all+=p[i]; } cout<<all<<endl; return 0; }
記在后面:
比賽前期過程中,隊伍陷入了一個誤區,總是在思考怎么去掉a+b+c!=d的方法。其實反向思考一下,把所有種類弄出來,想辦法記錄。取a+b+c==d不就可以了嗎?