DerrickLo發表於2024-04-26

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 \]