A 魔法
你有三個數 \(A,B,C\)。你有一種魔法,對三個數中的任何一個 \(x\) 使用一次魔法,可以使得這個數變成 \(\max(0,x-d)\)。其中,\(d\) 是固定的魔法引數。
你想把三個數變成優美的,也就是:
1、\(A,B,C\) 各不相同;
2、\(B\) 是最大的或是最小的;
你想知道,最少需要用幾次魔法。
傻逼分討。
#include<bits/stdc++.h>
#define int long long
using namespace std;
int d,a,b,c,ans1,ans2;
signed main(){
cin>>d>>a>>b>>c;
if(d==0){
if(a==b||b==c||a==c)cout<<-1;
else if(a<b&&c<b)cout<<"0\n";
else if(a>b&&c>b)cout<<0<<"\n";
else cout<<-1;exit(0);
}
int minx=(a==c)?max(a-d,0ll):min(a,c);
if(minx==0)ans1=1e18;
else if(b<minx)ans1=(a==c);
else ans1=(b-minx)/d+1+(a==c);
if(b==0)ans2=1e18;
else{
if(b<=a)ans2+=(a-b)/d+1;
if(b<=c)ans2+=(c-b)/d+1;
int nowa=(b<=a)?max(a-((a-b)/d+1)*d,0ll):a,nowc=(b<=c)?max(c-((c-b)/d+1)*d,0ll):c;
if(nowa==nowc){
if(nowa==0)ans2=1e18;
else ans2++;
}
}
cout<<(min(ans1,ans2)==1e18?-1:min(ans1,ans2))<<"\n";
return 0;
}
B 募捐
慈善晚宴開始了,一共有 \(N\) 個人,總共要募捐 \(S\) 元。
募捐從第一個人開始,按照順序依次進行,直到第 \(N\) 個人。由於這個順序是按照社會地位來排的,後面的人總是要比前面的人多捐至少 \(K\) 元。第一個人沒有限制,可以捐任意多錢,甚至可以捐 元。
你很好奇,想知道一共有多少種可能性,使得 \(N\) 個人正好捐了 \(K\) 元。
把第 \(i\) 個人的捐錢數減去 \(ki\),記 \(s\) 是減去後的總和,那麼題目轉化為:
- 求有多少個長度為 \(n\),單調不降的數列總和為 \(s\)。
那麼我們將其差分後記為 \((a_1,a_2,\ldots a_n)\),那麼:
\[\sum_{i=1}^{n}a_i\times(n-i+1)
\]
為定值。
這樣我們可以視作第 \(i\) 位的權值是 \(n-i+1\),問每一位選若干次總和為 \(s\) 有多少種選法。
可以直接完全揹包。
#include<bits/stdc++.h>
#define mod 1000000007
using namespace std;
int n,s,k,ans,dp[20005];
signed main(){
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
cin>>n>>s>>k,s-=(n-1)*n/2*k;
if(s<0)cout<<"0",exit(0);
dp[0]=1;
for(int i=1;i<=n;i++){
for(int j=n-i+1;j<=s;j++)dp[j]+=dp[j-(n-i+1)],dp[j]%=mod;
}
cout<<dp[s];
return 0;
}
C 旅行
\(N\) 對夫妻去旅行,分成若干組,每組至少要有一對夫妻,問一共有多少種不同的分法。
兩種分法不同,至少有一個組的成員不同。注意,分組是次序不相關的,例如以下兩種分成兩組的分法是相同的:\(\{Aa\}\{Bb\}\) 和 \(\{Bb\}\{Aa\}\)。
\[1\le N\le 600
\]