试题目录
A - 做游戏(签到)
- 思路: 这道题要求的是获胜局数,而不是得分!!!
Code:
#include <iostream>
using namespace std;
typedef long long ll;
int main(){
ll a,b,c; cin>>a>>b>>c;
ll x,y,z; cin>>x>>y>>z;
cout<<min(a,y)+min(b,z)+min(c,x)<<endl;
return 0;
}
B - 排数字(签到)
- 思路: 1 和 6 以外不需要考虑。要让 616 子串最多一定是 61616… ,这样后面的串可以用前面的 6 ,数量为 max(min(cnt_6-1, cnt_1), 0) 。(可以理解为前面一个 6 后面 16 循环)
Code:
#include <iostream>
#include <cmath>
using namespace std;
int main(){
int n; cin>>n;
string str; cin>>str;
int sum1=0,sum2=0;
for(int i=0;i<str.length();i++){
if(str[i]=='1') sum1++;
if(str[i]=='6') sum2++;
}
cout<<max(min(sum1,sum2-1),0)<<endl;
return 0;
}
C - 算概率(dp)
- 思路: 用 dp[i][j] 表示前 i 道题目做对了 j 道的概率,初始化 dp[0][0] = 1,第 j 道是否做对,有两种情况,状态转移方程为 dp[i][j] = dp[i-1][j] * (1-p[i]) + dp[i-1][j-1] * p[i] 。最后要注意的就是,概率有可能为负数,所以要加上 mod。
Code:
#include <iostream>
using namespace std;
typedef long long ll;
const int N=2e3+10;
const ll mod=1e9+7;
ll dp[N][N],p[N];
int main(){
int n; cin>>n;
for(int i=1;i<=n;i++)
cin>>p[i];
dp[0][0]=1;
for(int i=1;i<=n;i++)
for(int j=0;j<=i;j++)
dp[i][j]=(dp[i-1][j]*(1-p[i])+dp[i-1][j-1]*p[i])%mod;
for(int i=0;i<=n;i++){
if(dp[n][i]<0) cout<<dp[n][i]+mod<<' ';
else cout<<dp[n][i]<<' ';
}
cout<<endl;
return 0;
}
D - 数三角(计算几何)
- 思路: 先给所有坐标点排个序,然后暴力三层循环求法。一个三角形的三边长 a,b,c( c 最长 )满足 a^2 + b^2 < c^2(或存在两条边向量的点积 <0 ),则该三角形为钝角三角形。注意也要判断是否为三角形。
Code:
#include <iostream>
#include <algorithm>
#include <cmath>
using namespace std;
typedef long long ll;
struct node{
int x,y;
}arr[1000];
bool cmp(node a,node b){
if(a.x==b.x) return a.y<b.y;
return a.x<b.x;
}
int main(){
int n; cin>>n;
for(int i=1;i<=n;i++)
cin>>arr[i].x>>arr[i].y;
sort(arr+1,arr+1+n,cmp);
ll ans=0;
for(int i=1;i<=n;i++){
for(int j=i+1;j<=n;j++){
for(int k=j+1;k<=n;k++){
int a = (arr[i].x-arr[j].x)*(arr[i].x-arr[j].x)+(arr[i].y-arr[j].y)*(arr[i].y-arr[j].y);
int b = (arr[j].x-arr[k].x)*(arr[j].x-arr[k].x)+(arr[j].y-arr[k].y)*(arr[j].y-arr[k].y);
int c = (arr[i].x-arr[k].x)*(arr[i].x-arr[k].x)+(arr[i].y-arr[k].y)*(arr[i].y-arr[k].y);
if(c<a) swap(c,a);
if(c<b) swap(c,b);
if(sqrt(a)+sqrt(b)>sqrt(c) && a+b<c)
ans++;
}
}
}
cout<<ans<<endl;
return 0;
}
E - 做计数(数学)
- 思路: 两边平方,得
,显然仅当
都是整数且
为完全平方数时才会对应一个符合条件的
。所以先打表求出
以内的所有完全平方数并存入数组。然后枚举
以内所有的完全平方数的因字数总和,即为不同的正整数三元组数量
。
Code:
#include <iostream>
#include <cmath>
using namespace std;
typedef long long ll;
const int N=4e7;
ll a[N+10];
int main(){
int n; cin>>n;
int x;
for(int i=1;;i++){
if(i*i<=N)
a[i]=i*i;
else{
x=i-1;
break;
}
}
ll ans=0;
for(int i=1;i<=x;i++){
if(a[i]>n) break;
for(int j=1;j*j<=a[i];j++){
if(a[i]%j==0){
if(j*j==a[i]) ans++;
else ans+=2;
}
}
}
cout<<ans<<endl;
return 0;
}
F - 拿物品(思维+贪心)
- 思路: 要使得两人得分总和差值尽可能大,要么即要取使自己得分尽可能大的物品,也要取使对方得分尽可能少的物品,所以就要取 a+b 最大的物品。
Code:
#include <iostream>
#include <algorithm>
using namespace std;
const int N=2e5;
struct node{
int a,b,num;
}arr[N];
bool cmp(node x,node y){
return x.a+x.b>y.a+y.b;
}
int main(){
int n; cin>>n;
for(int i=1;i<=n;i++){
cin>>arr[i].a;
arr[i].num=i;
}
for(int i=1;i<=n;i++)
cin>>arr[i].b;
sort(arr+1,arr+1+n,cmp);
for(int i=1;i<=n;i++)
if(i%2)
cout<<arr[i].num<<' ';
cout<<endl;
for(int i=1;i<=n;i++)
if(i%2==0)
cout<<arr[i].num<<' ';
cout<<endl;
return 0;
}
G - 判正误(快速幂 + 模运算)
- 思路: 这道题就是一道快速幂模板题,唯一的难点就是会卡精度 (1e9+7) 。要注意快速幂里面不能用快速乘,快速乘一般用在 long long 数据范围,防止溢出。
Code:
#include <iostream>
using namespace std;
typedef long long ll;
const int mod=1e9+7;
ll q_pow(ll a,ll b,ll mod){
ll ans=1,res=a;
while(b){
if(b&1) ans=ans*res%mod;
res=res*res%mod;
b>>=1;
}
return ans%mod;
}
int main(){
int t; cin>>t;
while(t--){
ll a,b,c,d,e,f,g; cin>>a>>b>>c>>d>>e>>f>>g;
if(q_pow(a,d,mod)+q_pow(b,e,mod)+q_pow(c,f,mod)==g)
cout<<"Yes"<<endl;
else
cout<<"No"<<endl;
}
return 0;
}