第十一周训练情况
首先是A题
题目链接
https://vjudge.net/contest/439183#problem/A
当时的想法就是把a写成(0.5+)b;
ab=x;
(0.5+) b*b=x;
然后根据x/b/b>0.5 逐渐提高b的值,最后拿到临界值。这时我们就得到了b的值
再从1到b遍历选中a的值即可。题目较简单 不作过多说明了,下边附上代码:
#include<bits/stdc++.h>
using namespace std;
//scanf("%d",&n);
int main()
{
int n;
scanf("%d",&n);
for(int i=0;i<n;i++){
double x;
scanf("%lf",&x);
long long int b;
for(int j=1;;j++){
if(x/j/j<0.5){
b=j;
break;
}
}
int f=0;
for(double j=1;j<=b;j++){
for(double k=b;k>=j;k--){
if(j*k<x)break;
if(j*k==x&&j>=k*0.5){
f=1;
//cout<<"j: "<<j<<"k: "<<k<<endl;
goto c;
}
}
}
c: if(f==1){
cout<<1<<endl;
}
else cout<<0<<endl;
}
return 0;
}
G题
https://vjudge.net/contest/439183#problem/G
首先看到这道题,我还以为是要求面积的问题。
直接模拟了一次,每步加0.05但是,计算出来的面积的值相差太大。无奈直接重新看题,就发现面积是可以转换成公式的,上边是一个半圆,下边的式子也可以进行转换。而后化简之后用计算机实现,误差就小了很多
代码如下:
#include <bits/stdc++.h>
using namespace std;
#define pi 3.1415926535897932384
int main() {
int n;
cin>>n;
for(int i=0;i<n;i++){
double a,b;
cin>>a>>b;
double temp1 = a*a*pi/2;
double temp2 = 2*a*b;
double temp3 = 2*b*pi*(asin(1)+asin(-1));
cout<<(temp1 + temp2 -temp3)*2<<endl;
}
return 0;
}
B题
这道题是一个关于四个数字和三个字符随机排序的问题。
首先想到的是排列组合next_permutation函数,这个函数可以把数组元素进行排列组合。而后是考虑运算符在这四个排列之后的数值之间进行插入的问题。
注意这里可以分为连接,乘积,加减 运算符优先级从左到右。
相同优先级运算符运算顺序从左到右。
然后就想到用递归的方法枚举所有的情况,然后去重就可以得到最后的结果了。
代码如下:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXN = 1e4 + 7;
int ans,vis[MAXN];/is记录答案
map<pair<vector<int>,int>,int>mp;
void dfs(vector<int>vec,int op){
if(mp[{vec,op}]) return ;
mp[{vec,op}]++;
int siz = vec.size();
if(siz == 1){
if(!vis[vec[0]] && vec[0] >= 0) ans++,vis[vec[0]] = 1;
// cout<<ans<<endl;
return ;
}
if(op == 3){
vector<int>t;
t.push_back(vec[0] + vec[1]);
for(int i = 2;i < siz;i ++) t.push_back(vec[i]);
dfs(t,op);
t[0] = vec[0] - vec[1];
dfs(t,op);
}
if(op == 1 || op == 2){
dfs(vec,op+1);
if(siz == 2 && op == 1) return ;
for(int i = 0;i < siz - 1;i ++){
vector<int>t;
for(int j = 0;j < i;j ++) t.push_back(vec[j]);
if(op == 2){
t.push_back(vec[i] * vec[i+1]);
}
else if(op == 1){
t.push_back(vec[i+1] >= 10 ? vec[i]*100 + vec[i+1] : vec[i] * 10 + vec[i+1]);
}
for(int j = i + 2;j < siz;j ++) t.push_back(vec[j]);
dfs(t,op);
}
}
}
int main(){
vector<int>vec;
int x;
for(int i = 1;i <= 4;i ++) scanf("%d",&x),vec.push_back(x);
sort(vec.begin(),vec.end());
do{
dfs(vec,1);
// cout<<ans<<endl;
}while(next_permutation(vec.begin(),vec.end()));
printf("%d\n",ans);
return 0;
}
而后看到了某带佬的巨作,直接暴力插入set中去重,太强了。但是他的逻辑我还没理清,有空回来看看。
int main() {
IOS; rep (i, 0, 3) cin >> a[i]; sort(a, a + 4);
st.insert(a[0] + a[1] + a[2] + a[3]);
st.insert(a[0] * a[1] * a[2] * a[3]);
do {
st.insert(abs(a[0] + a[1] + a[2] - a[3]));
st.insert(abs(a[0] + a[1] - a[2] - a[3]));
st.insert(a[0] * a[1] + a[2] + a[3]);
st.insert(a[0] * a[1] + a[2] * a[3]);
st.insert(abs(a[0] * a[1] - a[2] - a[3]));
st.insert(abs(a[0] * a[1] - a[2] + a[3]));
st.insert(abs(a[0] * a[1] - a[2] * a[3]));
st.insert(a[0] + a[1] * a[2] * a[3]);
st.insert(abs(a[0] - a[1] * a[2] * a[3]));
st.insert(a[0] * 10 + a[1] + a[2] + a[3]);
st.insert(a[0] * 10 + a[1] + a[2] * a[3]);
st.insert(abs(a[0] * 10 + a[1] - a[2] - a[3]));
st.insert(abs(a[0] * 10 + a[1] - a[2] + a[3]));
st.insert(abs(a[0] * 10 + a[1] - a[2] * a[3]));
st.insert((a[0] * 10 + a[1]) * a[2] + a[3]);
st.insert((a[0] * 10 + a[1]) * a[2] - a[3]);
st.insert((a[0] * 10 + a[1]) * a[2] * a[3]);
st.insert(a[0] * 100 + a[1] * 10 + a[2] + a[3]);
st.insert(a[0] * 100 + a[1] * 10 + a[2] - a[3]);
st.insert((a[0] * 100 + a[1] * 10 + a[2]) * a[3]);
st.insert((a[0] * 10 + a[1]) + (a[2] * 10 + a[3]));
st.insert(abs((a[0] * 10 + a[1]) - (a[2] * 10 + a[3])));
st.insert((a[0] * 10 + a[1]) * (a[2] * 10 + a[3]));
} while (next_permutation(a, a + 4));
cout << st.size();
return 0;
}
补题:
J题
本来这道题我刚拿到题,想到的是这跟数值分解因数有一定的关系。然后就在分析能分解的因数的层数,然后就发现问题越分析越复杂。知道后面代码就非常的麻烦,就感觉思路出现了问题。
而后认为从头分析太复杂,就从最后分析,发现最后能判定输赢的时候都是遇到了一个质数。而想要能够选择的质数的最大值,那么是不是就我们选择的数应该是一个质数乘上一个质数的形式。而后有解
具体代码如下:
#include <iostream>
#include <bits/stdc++.h>
#define ref(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
int preme[200000]={0};
bool pre[200000]={0};
int cnt=0;
void su(int t){
ref(i,0,1)pre[i]=false;
ref(i,2,t){
if(pre[i]==false){
preme[cnt++]=i;
}
for(int j=i+i;j<=t;j=j+i){
pre[j]=true;
}
}
}
bool sushu(int x){
if(pre[x]==false)return true;
return false;
}
bool cj(int x){
int sq= sqrt(x);
ref(i,2,sq){
if(x%i==0)
if(sushu(i)&&sushu(x/i))return true;
}
return false;
}
int ma(int a){
if(a==1)
return 1;
else
{
for(int i=2; i*i<=a; i++)
{
if(a%i==0)
{
return ma(a/i)>ma(i)?ma(a/i):ma(i);
}
}
return a;
}
}
int main()
{
su(100000);
int n;
scanf("%d",&n);
//ref(i,0,100)cout<<preme[i]<<endl;
ref(i,1,n){
int x;
scanf("%d",&x);
if(sushu(x)) printf("0\n");
else if(cj(x)) printf("-1\n");
else {
ma(x);
// cout<<ma(x)<<" 11111"<<endl;
for(int i=x/ma(x);i>=2;i--){
if(sushu(i)&&x%(i*ma(x))==0){
printf("%d\n",i*ma(x));
break;
}
}
}
}
return 0;
}
C题
最开始的想法,从左到右消除,然后纸上模拟了一下就感觉有些问题。
比如AAAABBBA m=3的话,按上边的思路来的话就不太行。
最后看了大佬的代码,动态规划区间DP。
然后就仔细学了区间DP,根据长度和首个字母的位置。两层嵌套for循环,再带上中间的状态转移方程。
借鉴学习学习。
#include <iostream>
#include <bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define dec(i,a,b) for(int i=a;i>=b;i--)
#define INF 0x3f3f3f3f
using namespace std;
const int maxn=505;
int a[maxn];
int sz,m;
string t="RGBCMYK",s;
int dp [maxn][maxn][7],id[maxn];
//BBBRRRRRRGGGB 3
int main() {
cin>>s>>m;
if(m==1){
cout<<"Yes";
return 0;
}
memset(dp,-INF,sizeof(dp));
rep(i,0,t.size()-1)id[t[i]]=i;
rep(i,0,s.size()-1)dp[i][i][id[s[i]]]=1;
rep(len,2,s.size())rep(l,0,s.size()-len){
int r=l+len-1;
bool mer =0;
rep(i,l,r-1)rep(k,0,6)
{
dp[l][r][k]=max(dp[l][r][k],dp[l][i][k]+dp[i+1][r][k]);
//if(l==6&&r==7) cout<<l<<" "<<i<<" "<<k<<" "<<dp[l][i][k]<<" "<<i+1<<" "<<r<<" "<<dp[i+1][r][k]<<endl;
//cout<<dp[l][r][k]<<endl;
//cout<<l<<" "<<r<<" "<<dp[l][r][k]<<endl;
if(dp[l][r][k]>=m){
mer=1;
//cout<<"l and r "<<l<<" "<<r<<endl;
}
}
if(mer)rep(k,0,6)dp[l][r][k]=max(dp[l][r][k],0);
}
/* rep(k,0,6){
cout<<dp[0][s.size()-1][k]<<endl;
}*/
rep(k,0,6)if(dp[0][s.size()-1][k]>=m){
cout<<"Yes";
return 0;
}
cout<<"No";
return 0;
}