2019长沙学院暑假集训队第一次校赛
点击 >优先队列博客<
链接:https://ac.nowcoder.com/acm/contest/1068/A
来源:牛客网
题目描述
给定三个数:x, y, z;
找出一个数v使得:x|v, y|v, z|v,
那么v/x+v/y+v/z最小可能是多少?
说明:a|b表示a整除b。
输入描述:
三个整数x,y,z(1≤x,y,z≤1e8)
输出描述:
一个数,表示答案。
示例1
输入
1 2 4
输出
7
防止爆Long long 公式化简
(xy + yz + xz ) * v / xyz 式1
u=(x*y)/gcd(x,y)
u代入 -> v=(u*z) / gcd(u,z)
式1 化简为(xy + yz +xz) /gcd(x,y)/gcd(u,z)
#include<bits/stdc++.h> using namespace std; long long x,y,z; int main() { long long a[4]; cin>>a[0]>>a[1]>>a[2]; x=a[0]; y=a[1]; z=a[2]; long long res1=a[0]*a[1]; long long gccd1=__gcd(a[0],a[1]); res1=res1/gccd1; long long res2=__gcd(res1,a[2]); res1=gccd1; cout<<(x*y/res1/res2)+(y*z/res1/res2)+(x*z/res1/res2)<<endl; }
链接:https://ac.nowcoder.com/acm/contest/1068/G
来源:牛客网
题目描述
有一个字符串num= "0",你有n次操作,每次操作:1 x,在num右边加一个数字字符x,操作:0 x,在num左边加一个数字字符x,每次操作后都要输出新的num转变数字后模1e9+7的值。
输入描述:
输出描述:
n行每行一个数字
示例1
输入
10 1 0 1 2 0 0 0 1 0 2 0 1 0 1 1 0 1 0 1 0
输出
0 2 2 10002 210002 1210002 11210002 112100020 121000193 210001923
重点:取模运算 % ,具有可加性 (cs*=10)%mod 不影响正确结果 即在取模环境下 结果不变
#include<bits/stdc++.h>
#define mod 1000000007
using namespace std;
long long int cs=1;
long long num=0;
int main()
{
int n;
cin>>n;
while(n--)
{
int x,y;
cin>>x>>y;
cs*=10;
cs=cs%mod;
if(x==0)
{
num+=cs*y;
num=num%mod;
}
else if(x==1)
{
num*=10;
num+=y;
num=num%mod;
}
printf("%lld\n",num%mod);
}
}
链接:https://ac.nowcoder.com/acm/contest/1068/D
来源:牛客网
题目描述
有一个n * n的地图,每个格子(i, j)都有权值 ,现在你在(1, 1)起点位置, 每次你可以往下走或者往右走,每走到一个格子就会获得该格子的权值(起点的也算),问你走到终点(n, n)有多少条不同的路径,其路径上的权值总和刚好为2019。答案对1e9 + 7取模
输入描述:
第一行输入一个n(1 <= n <= 100) 接下来n行,每行输入n个数字,第i行j列为 aij(1 <= aij <=2019)
输出描述:
一个数,表示答案。
示例1
输入
2 1 2017 2017 1
输出
2
简单DP 构建三维dp数组dp[i][j][k] 在(i,j) 点 权值和为k 的 路径数
状态转移方程 dp[i][j][k]=dp[i-1][j][ k-a[i][j] ] + dp[i][j-1][ k-a[i][j] ]
记忆化搜索 递归
dp[i][j][k]+=go(i-1,j,k-a[i][j])+go(i,j-1,k-a[i][j]);
;
记忆化递归写法:
#include<bits/stdc++.h> #define mod 1000000007 using namespace std; long long dp[105][105][2020],dpp[105][105][2020]; int a[105][105]; int n; int ans=0; int go(int i,int j,int k) { if(k<0) return 0; if(i*j==0) { return dp[i][j][k]=0; } if(!dpp[i][j][k]) { dp[i][j][k]+=go(i-1,j,k-a[i][j])+go(i,j-1,k-a[i][j]); dp[i][j][k]%=mod; // printf("dp[%d][%d][%d]=%d\n",i,j,k,dp[i][j][k]); dpp[i][j][k]=1; } return dp[i][j][k]; } int main() { scanf("%d",&n); for(int i=1;i<=n;i++) { for(int j=1;j<=n;j++) { scanf("%d",&a[i][j]); } } dp[1][1][a[1][1]]=1; dpp[1][1][a[1][1]]=1; printf("%lld\n",go(n,n,2019)); }
递推写法:
#include<bits/stdc++.h> #define mod 1000000007 using namespace std; long long dp[105][105][2020],dpp[105][105][2020]; int a[105][105]; int n; int ans=0; int main() { scanf("%d",&n); for(int i=1;i<=n;i++) { for(int j=1;j<=n;j++) { scanf("%d",&a[i][j]); } } dp[1][1][a[1][1]]=1; dpp[1][1][a[1][1]]=1; for(int i=1;i<=n;i++) { for(int j=1;j<=n;j++) { for(int k=a[i][j];k<=2019;k++) { dp[i][j][k]+=dp[i-1][j][k-a[i][j]]; dp[i][j][k]%=mod; dp[i][j][k]+=dp[i][j-1][k-a[i][j]]; dp[i][j][k]%=mod; } } } printf("%lld\n",dp[n][n][2019]); }
链接:https://ac.nowcoder.com/acm/contest/1068/H
来源:牛客网
题目描述
给一个长度不超过1e5的字符串s,字符串元素只能是小写字母c, s, u其中的一个,现在定义四元组:[x1, x2, x3, x4] 合法的条件:s[x1] = c 且 s[x2] = c 且 s[x3] = s 且 s[x4] = u,且 x1 < x2 < x3 < x4,现在要求你把s切开成两个子串a, b(a,b不能是空串),求最小的a串合法四元组个数与b串合法四元组个数的差的绝对值
输入描述:
一个字符串s (2 <= |s| <= 1e5)
输出描述:
一个数,表示答案。
示例1
输入
ccsuuccssuu
输出
2
示例2
输入
ccsuccsu
输出
0
左扫描记录当前
C
CC
CCS
CCSU
右扫描记录当前数目
u
SU
CSU
CCSU
最后枚举所有分法 取最小值min(abs(sum1[i]-sum2[i+1],ans)
#include<bits/stdc++.h> #define ll long long using namespace std; ll dp[5],dpp[5],sum1[100005],sum2[100005]; char a[100005]; int main() { cin>>a; int l=strlen(a); for(int i=0;i<l;i++) { if(a[i]=='c') { dp[2]+=dp[1]; dp[1]++; } else if(a[i]=='s') { dp[3]+=dp[2]; } else if(a[i]=='u') { dp[4]+=dp[3]; } sum1[i]=dp[4]; } for(int i=l-1;i>=0;i--) { if(a[i]=='u') { dpp[1]++; } else if(a[i]=='s') { dpp[2]+=dpp[1]; } else if(a[i]=='c') { dpp[4]+=dpp[3]; dpp[3]+=dpp[2]; } sum2[i]=dpp[4]; } ll ans=1e18; for(int i=0;i<l-1;i++) { ans=min(ans,abs(sum1[i]-sum2[i+1])); } printf("%lld\n",ans); }
链接:https://ac.nowcoder.com/acm/contest/1068/E
来源:牛客网
排位赛
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld题目描述
众所周知王者荣耀排位赛可以禁英雄,现在有n个英雄,每对英雄之间有配合度,现在你要选出5个英雄去参加比赛,但是对方能禁止两个英雄,使得你不能选取被禁止的英雄,假设对方采取最优策略禁止英雄,求你选取英雄后所能得到最大的总配合度
输入描述:
第一行输入一个n(7 <= n <= 20) 接下来n行,每行输入n个数字,第i行j列为aij,表示英雄i和英雄j的配合度(0 <= aij <= 1e5)
输出描述:
一个数,表示答案。
示例1
输入
7 0 8 5 1 10 5 9 8 0 3 5 6 6 2 5 3 0 2 2 6 3 1 5 2 0 7 2 5 10 6 2 7 0 4 3 5 6 6 2 4 0 2 9 2 3 5 3 2 0
输出
36
dfs回溯剪枝 枚举 所有情况 因对方最有策略禁英雄 则只能采取min值
#include<bits/stdc++.h> using namespace std; int aa[25][25]; int a[25]; int stk[6]; int cnt=0; int x,y; int n; int ans=1e9,res; int dfs(int t) { if(cnt==5) { int sum=0; for(int i=0;i<4;i++) { for(int j=i+1;j<5;j++) { sum+=aa[stk[i]][stk[j]]; } } res=max(res,sum); return 0; } if(t>n) return 0; dfs(t+1); if(t!=x&&t!=y) { stk[cnt++]=t; dfs(t+1); // stk.pop(); cnt--; } } int main() { cin>>n; for(int i=1;i<=n;i++) { for(int j=1;j<=n;j++) { scanf("%d",&aa[i][j]); } } for(int i=1;i<n;i++) { for(int j=i+1;j<=n;j++) { res=0; x=i; y=j; dfs(1); ans=min(ans,res); } } printf("%d\n",ans); }
链接:https://ac.nowcoder.com/acm/contest/1068/C
来源:牛客网
构造B数组
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld题目描述
给一个长度为n的数组a,现在要你构造一个长度为n的数组b,使得数组b的元素总和恰好为m且每个元素最小值不能小于0,且 最小,求出这个最小值
输入描述:
第一行输入两个数n,m (1 <= n, m <= 1e5) 第二行输入n个数表示ai(1 <= ai <= 1e3)
输出描述:
一个数,表示答案
示例1
输入
3 1 1 2 3
输出
21
示例2
输入
3 5 1 1 2
输出
1
点击 >优先队列博客<
解法:贪心、确保每一次增加 都使得结果增加最小 在优先队列中不断取最小增加的情况不断更新队列
注意!:更新后的结构体未被修改 需要从队中逐个取出进行求和
优先队列 priority_queue
结构体重载 < 运算符
#include<bits/stdc++.h> #define ll long long using namespace std; long long sum=0; struct node { int a; int b; int v; bool operator < (const node &S) const { return v > S.v; } }num[100005]; priority_queue<node> que; int n,m; int ct(int a,int b) { return a*(a-b)*(a-b); } int main() { scanf("%d%d",&n,&m); for(int i=0;i<n;i++) { scanf("%d",&num[i].a); num[i].b=0; num[i].v=ct(num[i].a,num[i].b+1)-ct(num[i].a,num[i].b); que.push(num[i]); } for(int i=0;i<m;i++) { node t=que.top(); que.pop(); t.b++; t.v=ct(t.a,t.b+1)-ct(t.a,t.b); que.push(t); } for(int i=0;i<n;i++) { node tt=que.top(); que.pop(); sum+=ct(tt.a,tt.b); } cout<<sum<<endl; }