T1
题解
对于每一个数,循环每一位统计不同数的个数,判断是否小于k,是则答案数+1
代码
#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#include<algorithm>
#include<iomanip>
using namespace std;
#define rep(i,s,t) for(int i=s;i<=t;i++)
#define mem(a,s) memset(a,s,sizeof(a))
typedef long long LL;
const int N=1e6;
int n,k;
bool sum[10];
int main(){
//freopen("in.txt","r",stdin);
cin.sync_with_stdio(false);
cin >> n >> k;
int ans = 0;
rep(i,1,n){
string s;
mem(sum, 0);
cin >> s;
for(auto it:s)
sum[it - '0'] = 1;
int tt = 0;
rep(i, 0, 9) if (sum[i])
tt++;
if(tt<k)
ans++;
}
cout << ans;
return 0;
}
T2
题解
这个题不是最小圆覆盖!!不是!!不是!!
一开始浪费了很多时间,后来才发现是“中心位于发射点上”。
这样的话我们直接枚举每一个中心,求取和其他点最大距离,之后求出这些最大距离中的最小距离。
由于输出平方,整个过程中用不到浮点类型,所以最后直接输出lld+后缀.00即可
代码
#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#include<algorithm>
#include<iomanip>
using namespace std;
#define rep(i,s,t) for(int i=s;i<=t;i++)
#define mem(a,s) memset(a,s,sizeof(a))
typedef long long LL;
const int N=1000+10;
pair<LL,LL> a[N];
int n;
int main(){
//freopen("in.txt","r",stdin);
cin.sync_with_stdio(false);
cin>>n;
rep(i,1,n)
cin >> a[i].first >> a[i].second;
if(n==1){
cout << a[1].first <<".00"<< ' ' << a[1].second <<".00"<< endl;
cout << "0.00";
return 0;
}
sort(a + 1, a + n + 1);
LL mn=-1, idx;
rep(i,1,n){
LL mx = 0;
rep(j,1,n){
LL r=(a[i].second - a[j].second) * (a[i].second - a[j].second) + (a[i].first - a[j].first) * (a[i].first - a[j].first);
if(r>mx)
mx = r;
}
if(mn==-1||mx<mn)
mn = mx, idx = i;
}
cout << a[idx].first <<".00"<< ' ' << a[idx].second <<".00"<< endl;
cout << mn << ".00";
return 0;
}
T3
题解
求解有没有满足条件的树,考虑枚举每一种树,每一个节点做根的情况下,依据二叉搜索树的性质,左子树都比根小,右子树都比根大,即左子树就是当前根左边区间的元素,右子树就是当前右边区间的元素,也就是说我们只需要求出每一个区间的情况即可,这就是区间dp,dp[l][r][root]代表节点为a[l,[r][根为root(root属于a[l,r])的子树是否可以构造出满足条件的,则转移方程为dp[l][r][k]=dp[l][k-1][x]&&dp[k+1][r][y]&&gcd[x][k]>1&&gcd[k][y]>1,但是这样复杂度太高了,有没有优化的做法?我们可以发现k这个状态是可以合并的因为我们在枚举k的过程中,每一个子状态都是要么以右边邻近节点为根成为左子树,要么以左边邻近节点为根成为右子树,这样我们其实可以在子状态枚举k的过程中就求出能和左边or右边构造成功的可能,这样状态就缩减成dp[l][r][2],转移方式见代码
注意!!存在k=l,k=r这两种边缘情况,即一个子树为空,这个需要特殊判断!!
最后需要再枚举一遍以每一个元素为根的情况,因为dp[1][n]的两个状态不存在。
代码
#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#include<algorithm>
#include<iomanip>
using namespace std;
#define rep(i,s,t) for(int i=s;i<=t;i++)
#define mem(a,s) memset(a,s,sizeof(a))
typedef long long LL;
const int N=710;
int n;
int a[N];
int cal[N][N];
bool dp[N][N][2];
int gcd(int x,int y){return y == 0 ? x : gcd(y,x%y);}
int main(){
//freopen("in.txt","r",stdin);
cin.sync_with_stdio(false);
int T;
cin>>T;
while(T--){
cin >> n;
rep(i,1,n)
cin>>a[i];
if(n==1){
cout << "Yes";
if(T>=1)
cout << endl;
continue;
}
rep(i, 1, n)
rep(j, 1, n)
cal[i][j] = gcd(a[i], a[j]);
mem(dp, 0);
rep(siz,1,n){
rep(l,1,n-siz+1){
int r = l + siz - 1;
rep(k,l,r){
if ((k==l||dp[l][k - 1][1])&&(k==r||dp[k + 1][r][0])){
if(l!=1&&cal[l-1][k]>1)
dp[l][r][0] = 1;
if(r!=n&&cal[k][r+1]>1)
dp[l][r][1] = 1;
}
}
}
}
bool jud=0;
rep(k,1,n)
if((k==1||dp[1][k-1][1])&&(k==n||dp[k+1][n][0])){
jud=1;
break;
}
cout << (jud ? "Yes" : "No");
if(T>=1)
cout << endl;
}
return 0;
}