1. 程式人生 > >ICPC-思維-CF#342div2 A(!)+B+C

ICPC-思維-CF#342div2 A(!)+B+C

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define mem(a,b) memset(a,b,sizeof(a))
const ll mod=998244353;
const int maxn=2e5;
int main(){
	int t;
	ll n,a,b,c;
	cin>>n;
	cin>>a>>b>>c;
    ll one=a,two=b-c;
    ll sum1=n/one,yu1=n%one,ci;
    while(yu1/b>0){
        ci=(yu1-c)/two;
        yu1=yu1-ci*two;
        sum1+=ci;
    }
    ll yu2=n,sum2=0,ans=0;
    while(yu2/b>0){
        ci=(yu2-c)/two;
        yu2=yu2-ci*two;
        sum2+=ci;
    }
    sum2+=yu2/one;
    yu2=yu2%one;

    ans=max(ans,sum2);
    ans=max(sum1,ans);
    cout<<ans<<endl;
	return 0;
}

下面是我一開始想的,比較醜
首先,這個兩種方案同時比較,可以避免做一些錯誤的貪心判斷
再者,在判斷剩下的錢中是否要進行購入的時候,判斷標準是錢數而不是個數
注意:我認為(剩錢-b)/(b-c)是第二種交換的次數
但是我對於僅大於b卻不能進行第二種交換的剩錢進行特判
這種錢的判斷標準是選a或者選b的最小錢數

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define mem(a,b) memset(a,b,sizeof(a))
const ll mod=998244353;
const int maxn=2e5;
int main(){
	int t;
	ll n,a,b,c;
	cin>>n;
	cin>>a>>b>>c;
    ll one=a,two=b-c;
    ll sum1=n/one,yu1=n%one,ci;
    while(yu1/b>0){
        ci=(yu1-b)/two;
        if(ci==0&&yu1>=b){//b-2b
            if(yu1/a>0&&yu1/a*a<yu1/b*two){
                yu1=yu1-yu1/a*a;
                sum1=sum1+yu1/a;
            }
            else {
                yu1-=two;
                sum1++;
            }
        }
        else{
            yu1=yu1-ci*two;
            sum1+=ci;
        }
    }
    
    ll yu2=n,sum2=0,ans=0;
    while(yu2/b>0){
        ci=(yu2-b)/two;
        if(ci==0&&yu2>=b){
            if(yu2/a>0&&yu2/a*a<yu2/b*two){
                yu2=yu2-yu2/a*a;
                sum2+=yu2/a;
            }
            else {
                yu2-=two;
                sum2++;
            }
        }
        else{
            yu2=yu2-ci*two;
            sum2+=ci;
        }
    }
    sum2+=yu2/one;
    yu2=yu2%one;
    
    ans=max(ans,sum2);
    ans=max(sum1,ans);
    cout<<ans<<endl;
	return 0;
}

B
這個題,就是找不可重疊的子串數量,暴力即可,找到一個子串就將最後一個字元改成#

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define mem(a,b) memset(a,b,sizeof(a))
const ll mod=998244353;
const int maxn=2e5;
string s,a;
bool check(int i){
    for(int j=1;j<a.size();j++){
        if(s[i+j]!=a[j])return false;
    }
    return true;
}
int main(){
	cin>>s;
	cin>>a;
	int sum=0;
	for(int i=0;i<s.size();i++){
        if(a[0]==s[i]){
            if(check(i)){
                sum++;
                s[i+a.size()-1]='#';
            }
        }
	}
    cout<<sum<<endl;
	return 0;
}

C
分成,[1,k-1] 和 [k,n]
前半段,1 2 …(k-1)*n 這樣一行一行去填充
後半段,(k-1)*n+1 (k-1)*n+2 這樣一行一行再填充
就OK了

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define mem(a,b) memset(a,b,sizeof(a))
const ll mod=998244353;
const int maxn=500;
int num[maxn+5][maxn+5];
int main(){
    int n,k;
	cin>>n>>k;
	int cnt=1;
	for(int j=1;j<=n;j++){
        for(int i=1;i<k;i++){
            num[j][i]=cnt;
            cnt++;
        }
	}
	//cout<<cnt<<endl;
	for(int j=1;j<=n;j++){
        for(int i=k;i<=n;i++){
           num[j][i]=cnt;
           cnt++;
        }
	}
	ll ans=0;
	for(int i=1;i<=n;i++)ans+=num[i][k];
	cout<<ans<<endl;
	for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++){
            cout<<num[i][j]<<" ";
        }
        cout<<endl;
	}
	return 0;
}