递归,排序算法和贪心思维
1.汉诺塔
#include<bits/stdc++.h>
using namespace std;
int main()
{
//2^n-1
cout<<(unsigned long long)pow(2,64)<<endl;
return 0;
}
2.数字三角形
#include<bits/stdc++.h>
#define int long long
using namespace std;
int n;
int a[110][110],sum[110][110];
signed main()
{
cin>>n;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=i;j++)
{
cin>>a[i][j];
}
}
sum[1][1]=a[1][1];
for(int i=2;i<=n;i++)
{
for(int j=1;j<=i;j++)
{
sum[i][j]=a[i][j]+max(sum[i-1][j],sum[i-1][j-1]);
}
}
cout<<max(sum[n][(n+1)/2],sum[n][(n+2)/2])<<endl;
return 0;
}
3.奇妙变换
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int mod=998244353;
int fun(int x)
{
if(x<=10)
{
return x*(x-1)%mod;
}
else
{
return 2*x*fun(x-6)%mod;
}
}
signed main()
{
int n;
cin>>n;
if(n<=10)
{
cout<<n*(n-1)%mod<<endl;
}
else
{
cout<<2*n*fun(n-6)%mod<<endl;
}
return 0;
}
4.全排列的价值
#include <iostream>
using namespace std;
const int MOD = 998244353;
const long long inv4 = 748683265; // 4的逆元模998244353
int main() {
int n;
cin >> n;
if (n < 2) {
cout << 0 << endl;
return 0;
}
long long fact = 1;
for (int i = 2; i <= n; ++i) {
fact = fact * i % MOD;
}
long long ans = fact * n % MOD;
ans = ans * (n - 1) % MOD;
ans = ans * inv4 % MOD;
cout << ans << endl;
return 0;
}
5.数正方形
#include<bits/stdc++.h>
#define int long long
using namespace std;
signed main()
{
// n*n+(n-1)*(n-1)*2+(n-2)*(n-2)*3+..+()+n
int n;
cin>>n;
int ans;
for(int i=1; i<n; i++)
{
ans+=i*(n-i)*(n-i);
ans%=1000000007;
}
cout<<ans;
return 0;
}
6.高塔登顶方案
#include<bits/stdc++.h>
#define int long long
using namespace std;
int n,m,k;
const int mod=1e9+7;
int dp[100010]; //方案数
int sum[100010]; //表示从 dp[0] 到 dp[i] 的累加和
signed main()
{
cin>>n>>m>>k;
dp[1]=1;
sum[1]=1;
for(int i=2; i<=n; i++) //有序先遍历背包
{
int r=max(i-m,0LL); //LL避免类型不一致出问题
int l=max(i-k,1LL); //方便后面sum[l-1]
dp[i]=(sum[r]-sum[l-1]+mod)%mod;
sum[i]=(sum[i-1]+dp[i])%mod;
}
cout<<dp[n]<<endl;
return 0;
}
7.封闭图形个数
#include<bits/stdc++.h>
#define int long long
using namespace std;
int n;
int a[200010];
map<int, int>p;
vector<pair<int,int>>a1;
int fun(int x)
{
int x1=0;
while(x>0)
{
x1+=p[x%10];
x/=10;
}
return x1;
}
bool cmp(const pair<int, int>& x, const pair<int, int>& y)
{
if(x.second==y.second)
{
return x.first<y.first;
}
return x.second<y.second;
}
signed main()
{
p[1] = 0;
p[2] = 0;
p[3] = 0;
p[5] = 0;
p[7] = 0;
p[0] = 1;
p[4] = 1;
p[6] = 1;
p[9] = 1;
p[8] = 2;
cin>>n;
for(int i=0; i<n; i++)
{
cin>>a[i];
a1.push_back({a[i],fun(a[i])});
}
sort(a1.begin(),a1.end(),cmp);
for(int i=0; i<n; i++)
{
cout<<a1[i].first<<" ";
}
return 0;
}
8.错误票据
#include<bits/stdc++.h>
#define int long long
using namespace std;
int n;
vector<int>a;
signed main()
{
cin>>n;
getchar();
string line;
while(n--)
{
getline(cin,line);
stringstream ss(line);
int num;
while(ss>>num)
{
a.push_back(num);
}
}
sort(a.begin(),a.end());
int m,n;
for(int i=0;i<a.size()-1;i++)
{
if((a[i]+1)!=a[i+1] && a[i]!=a[i+1]) //断号且非重号情况
{
m=a[i]+1;
}
if(a[i]==a[i+1]) //重号
{
n=a[i];
}
}
cout<<m<<" "<<n<<endl;
return 0;
}
9.训练士兵
#include<bits/stdc++.h>
#define int long long
using namespace std;
int n,s;
vector<pair<int,int>>nums;
int sum=0,sum1=0,sign=0;
bool cmp (const pair<int,int> &x,const pair<int,int> &y)
{
return x.second>y.second;
}
signed main()
{
cin>>n>>s;
while(n--)
{
int p,c;
cin>>p>>c;
nums.push_back({p,c});
}
sort(nums.begin(),nums.end(),cmp); //贪心:局部最优多个士兵单次训练(pi+...+pn>s) n之前的单次训练划算
for(int i=0; i<nums.size(); i++)
{
sum+=nums[i].first;
if(sum>=s)
{
sign=i; //sign之前的单次训练划算,组团训练只考虑训练次数最多士兵花费
break;
}
}
for(int i=0; i<sign; i++)
{
sum1+=nums[i].first*(nums[i].second-nums[sign].second); //非组团训练花费
}
sum1+=s*nums[sign].second; //组团训练花费
cout<<sum1<<endl;
return 0;
}
10.三国游戏
//博弈论:
假设玩家最先拿取武将a,c;计算机因此拿取武将b,d。根据规则,a与b默契值最高,c与d默契值最高
//则b与d的默契值不可能最高,最多为第二高(最高默契被破坏) 即计算机<=玩家,玩家必胜
//那么,只要找到【第二高的默契值】最高的一对武将,拿取之后便一定胜利。
#include<bits/stdc++.h>
#define int long long
using namespace std;
int n;
int a[510][510];
int fun(int i)
{
int b[510];
for(int j=0; j<n-1; j++)
{
b[j]=a[i][j]; //遍历每一列,选取每个武将默契值第二大的另一个武将
}
sort(b,b+n-1);
return b[n-3];
}
signed main()
{
cin>>n;
for(int i=0; i<n-1; i++)
{
for(int j=i; j<n-1; j++)
{
cin>>a[i][j];
a[j][i]=a[i][j];
}
}
int max1=0;
for(int i=0; i<n-1; i++)
{
max1=max(max1,fun(i));
}
cout<<1<<endl<<max1<<endl;
return 0;
}
#include<bits/stdc++.h>
#define int long long
using namespace std;
int n;
int a[100010],b[100010],c[100010];
int w1[100010],w2[100010],w3[100010];
int sum1=0,sum2=0,sum3=0,sign1=-1,sign2=-1,sign3=-1;
signed main()
{
cin>>n;
for(int i=0; i<n; i++) cin>>a[i];
for(int i=0; i<n; i++) cin>>b[i];
for(int i=0; i<n; i++) cin>>c[i];
for(int i=0; i<n; i++)
{
w1[i]=a[i]-b[i]-c[i];
w2[i]=b[i]-a[i]-c[i];
w3[i]=c[i]-a[i]-b[i];
}
sort(w1,w1+n,greater<int>()); //存在负数,要使事件最多,应从大加到小
sort(w2,w2+n,greater<int>());
sort(w3,w3+n,greater<int>());
for(int i=0; i<n; i++)
{
sum1+=w1[i];
if(sum1>0)
{
sign1=i+1;
}
else
{
break;
}
}
for(int i=0; i<n; i++)
{
sum2+=w2[i];
if(sum2>0)
{
sign2=i+1;
}
else
{
break;
}
}
for(int i=0; i<n; i++)
{
sum3+=w3[i];
if(sum3>0)
{
sign3=i+1;
}
else
{
break;
}
}
int ans=-1;
ans=max(max(sign1,sign2),sign3);
cout<<ans<<endl;
return 0;
}