小红的字符串
代码
#include<iostream>
#include<map>
using namespace std;
string a;
map<char,int>S;
int main(){
cin>>a;
for(int i=0;i<a.size();i++){
S[a[i]]++;
}
int maxv=0;
for(auto [v,w]:S){
maxv=max(maxv,w);
}
cout<<a.size()-maxv;
return 0;
}
小红的序列乘积
思路
就是直接看个位数就可以了,别的不管。
#include<iostream>
#define int long long
using namespace std;
const int N = 2e5+10;
int w[N];
int n;
int res;
signed main(){
cin>>n;
int sum=1;
for(int i=1;i<=n;i++){
int x;
cin>>x;
int k=x%10;
sum*=k;
sum%=10;
// cout<<k<<endl;
if(sum%10==6){
res++;
}
}
cout<<res;
return 0;
}
小红的数组重排
思路
我们就直接排个序即可。
#include<iostream>
#include<algorithm>
#define int unsigned long long
using namespace std;
const int N = 5e5+10;
int w[N];
int a[N],b[N];
int n;
int m1,m2;
signed main(){
cin>>n;
for(int i=1;i<=n;i++)cin>>w[i];
sort(w+1,w+1+n);
bool f=false;
for(int i=1;i<n-1;i++){
if(w[i]*w[i+1]>=w[i+1]*w[i+2]){
f=true;
break;
}
}
if(f)puts("NO");
else{
puts("YES");
for(int i=1;i<=n;i++){
cout<<w[i]<<' ';
}
}
return 0;
}
虫洞操纵者
思路
本质上就是bfs,但只不过我们这道题建图有点麻烦,我们得考虑每行的最近点对和每列的,我们要搞虫洞,我们可以用二维数组来装一下在 ( x , y ) (x,y) (x,y) 坐标下,每行或每列的最近 1 1 1 的位置,然后每行每列找到之后,我们就将它们建图,最后我们只需要跑个最短路(我这边用的是bfs)即可解决。
- 这边注意一下的就是,我们是扩展了图,就是把给定的图的外部全部设为 1。
#include<iostream>
#include<algorithm>
#include<cstring>
#include<queue>
#define x first
#define y second
using namespace std;
typedef pair<int,int>PII;
const int N = 3e6+10,M = 4*N,S=1e3+10;
int e[M],ne[M],h[N],idx;
bool st[N];
int n;
int dist[N];
int w[S][S];
queue<int>q;
int dx[]={-1,0,1,0},dy[]={0,1,0,-1};
int pre[S][S],up[S][S];
int get(int x,int y){
return (x-1)*n+y;
}
void add(int a,int b){
e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}
int bfs(){
memset(dist,0x3f,sizeof dist);
dist[1]=0;
q.push(1);
while(q.size()){
int ver=q.front();
q.pop();
for(int i=h[ver];~i;i=ne[i]){
int j=e[i];
if(dist[j]>dist[ver]+1){
dist[j]=dist[ver]+1;
q.push(j);
// cout<<(j-1)/n+1<<' '<<(j-1)%n+1<<endl;
}
}
}
return dist[n*n];
}
int main(){
cin>>n;
for(int i=0;i<=n+5;i++){
for(int j=0;j<=n+5;j++){
w[i][j]=1;
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
cin>>w[i][j];
}
}
memset(h,-1,sizeof h);
for(int i=1;i<=n+1;i++){
// pre[i][0]=0;
for(int j=1;j<=n+1;j++){
if(w[i][j]==1){
pre[i][j]=j;
}else{
pre[i][j]=pre[i][j-1];
}
}
}
for(int j=1;j<=n+1;j++){
// up[0][j]=0;
for(int i=1;i<=n+1;i++){
if(w[i][j]==1){
up[i][j]=i;
}else{
up[i][j]=up[i-1][j];
}
}
}
for(int i=1;i<=n+1;i++){
for(int j=1;j<=n+1;j++){
if(i==n+1&&j==n+1)continue;
if(w[i][j]==1){
if(j>=2&&w[i][j-1]==0){
add(get(i,j-1),get(i,pre[i][j-1]+1));
add(get(i,pre[i][j-1]+1),get(i,j-1));
}
if(i>=2&&w[i-1][j]==0){
add(get(i-1,j),get(up[i-1][j]+1,j));
add(get(up[i-1][j]+1,j),get(i-1,j));
}
}
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(w[i][j]==0){
for(int k=0;k<4;k++){
int a=dx[k]+i,b=dy[k]+j;
if(a<1||b<1||a>n||b>n||w[a][b]==1)continue;
add(get(i,j),get(a,b));
add(get(a,b),get(i,j));
}
}
}
}
int t=bfs();
if(t>0x3f3f3f3f/2)puts("-1");
else cout<<t;
return 0;
}
小红的序列乘积2.0
思路
这道题就是dp问题,类似数位dp,我们可以设:f[i][j]表示已经到了第i个位置,当前位的是j的方案数集合。
那么它的状态转移也很容易:
f[i][j*w[i]%10]=f[i-1][j]+f[i][j*w[i]%10]
然后如果当前位是 6 的话,我们就 f[i-1][j]*2^{n-i}
即可。(为什么是这个式子呢,因为前面的位数已经定下来了,后面的位数的方案是
2
n
−
i
2^{n-i}
2n−i,也就是选和不选两种情况)
//数位dp,f[i][j]表示已经到了第i个位置,当前位的是j的方案数集合
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
#define int long long
const int N = 1e5+10,mod=1e9+7;
int f[N][12],g[N];
int n;
int w[N];
int qmi(int a,int b){
int res=1;
while(b){
if(b&1)res=res*a%mod;
a=a*a%mod;
b>>=1;
}
return res;
}
signed main(){
cin>>n;
for(int i=1;i<=n;i++)cin>>w[i],w[i]%=10;
f[0][1]=1;
int ans=0;
for(int i=1;i<=n;i++){
for(int j=0;j<10;j++){
(f[i][j]+=f[i-1][j])%=mod;
(f[i][j*w[i]%10]+=f[i-1][j])%=mod;
if(j*w[i]%10==6){
(ans+=f[i-1][j]*qmi(2,n-i))%=mod;
}
}
}
cout<<ans;
return 0;
}
灯下定影
思路
这道题就是计算几何的基础应用,其实就是算直线跟圆的交点,然后所有交点算完之后存储起来最后做区间合并就可以了。
代码(包含计算几何的部分板子)
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<vector>
#define x first
#define y second
using namespace std;
typedef pair<double,double>PDD;
const int N = 1e5+10;
const double eps=1e-8;
const double PI=acos(-1);
double r,x;
int n;
vector<PDD> v;
int sign(double x){
if(x<0)return -1;
if(fabs(x)<eps)return 0;
return 1;
}
int cmp(double x,double y){
if(x<y)return -1;
if(fabs(x-y)<eps)return 0;
return 1;
}
PDD operator+(PDD a,PDD b){
return {a.x+b.x,a.y+b.y};
}
PDD operator-(PDD a,PDD b){
return {a.x-b.x,a.y-b.y};
}
PDD operator/(PDD a,double t){
return {a.x/t,a.y/t};
}
double operator*(PDD a,PDD b){
return a.x*b.y-a.y*b.x;
}
double operator&(PDD a,PDD b){
return a.x*b.x+a.y*b.y;
}
double get_len(PDD a){
return sqrt(a&a);
}
PDD operator*(PDD a,double b){
return {a.x*b,a.y*b};
}
double area(PDD a,PDD b,PDD c){
return (b-a)*(c-a);
}
bool on_segment(PDD p,PDD a,PDD b){
return sign((p-a)&(p-b))<=0;
}
PDD get_line_intersaction(PDD p,PDD v,PDD q,PDD w){
PDD u=p-q;
double t=(w*u)/(v*w);
return p+v*t;
}
double get_dist(PDD a,PDD b){
double dx=a.x-b.x;
double dy=a.y-b.y;
return sqrt(dx*dx+dy*dy);
}
int main(){
PDD p0;
cin>>p0.x>>p0.y>>r>>n>>x;
for(int i=1;i<=n;i++){
PDD p1,p2;
double s;
cin>>p1.x>>p1.y>>p2.x>>p2.y>>s;
PDD v1=p0-p1;
PDD v2=p2-p1;
double len1=(v1&v2)/get_len(v2);
if(len1<0)continue;
double len2=get_len(v1);
double len3=sqrt(len2*len2-len1*len1);//圆心到直线的距离
if(len3>r)continue;
double len4=sqrt(r*r-len3*len3);
double xl=(len1-len4)/s;
double xr=(len1+len4)/s+x;
v.push_back({xl,xr});
}
sort(v.begin(),v.end());
double ans=0;
double l=0,r=0;
for(auto& [xl,xr]:v){
// cout<<xl<<' '<<xr<<endl;
if(r<xl){
ans+=r-l;
l=xl,r=xr;
}else{
r=max(xr,r);
}
}
ans+=r-l;
printf("%.10lf",ans);
return 0;
}