加载中...

寒假的比赛题

对于多组输入样例t的题 最好在while(t--)
里面进行这个初始话 防止用了上次样例的结果 还要注意cout<<endl;
然而还需注意当需要多次进行数组初始化可能导致超时
数据小的时候优先考虑爆搜,然后才是找规律。
dfs可以画出递归搜索树 知道i和j是什么
dfs题目 记得vis 和 vector 都要清空0

可以只让q[n+1]这段变成0;
那些样例解释要求区间 但是答案只有一个数字的很有可能是找规律 用排列组合计算

0.深渊水妖 找极长不严格上升段

输入
1
7
1 3 5 2 4 6 3
输出
1 3 4 6

#include<bits/stdc++.h>
#define int long long
const int N=3e6+10;
using namespace std;
 int q[N]={0};//全局变量,降低复杂度

signed main(){
    int t;cin>>t;    
    while(t--){
        int n;
        cin>>n;
        q[n+1]=0;//可以只让q[n+1]这段变成0,否则多次定义也会变成0;
       int pre,res=0;
        for(int i=1;i<=n;i++){
           scanf("%d",&q[i]);
             if(i==1||q[i]<q[i-1]){
                pre=q[i];
            }
            res=max(res,q[i]-pre);
           
        }
      int x,y;
        for(int i=1;i<=n;i++){
            if(i==1||q[i-1]>q[i]){
                pre=i;
            }
            y=i;
            if(q[y]-q[pre]==res&&q[y]>q[y+1])
            cout<<pre<<" "<<y<<" ";            
        }
        cout<<endl;
    }
}

//下面用vector<pair<int,int>>
 for(int i = 1; i <= n + 1; i ++ )
        {
           if(a[i] >= a[i - 1]) r = i;
           else
           {
               if(a[r] - a[l] >= len)
               {
                   if(a[r] - a[l] > len) v.clear(), len = a[r] - a[l];
                   v.push_back({l, r});
               }
               l = i, r = i;
           }
        }
///

1.顽皮恶魔 保护植物

输入样例
1
5 5
ZPZPZ
PPZP
ZPZPZ
PZPZP
ZP
PZ


#include<bits/stdc++.h>
using namespace std;
const int N = 1010;
int dx[8] = {1, 1, 1, 0, -1, -1, -1, 0};
int dy[8] = {1, 0, -1, -1, -1, 0, 1, 1};
int main()
{
    int t;
    cin >> t;
    while(t--)
    {
        char a[N][N];
        int n,m;
        scanf("%d%d",&n,&m);
        for(int i=1; i<=n; i++)
        {
             scanf("%s",a[i]+1);//这样读入字符串防止回车符
        }
       for (int i = 1; i <= n; ++i)
        for (int j = 1; j <= m; ++j) {
            if (a[i][j] == '*') {
                for (int k = 0; k < 8; ++k) {
                    int nx = i + dx[k], ny = j + dy[k];
                   if (nx >= 1 && nx <= n && ny >= 1 && ny <= m && a[nx][ny] == 'P')
                        a[nx][ny] = 's';//不要写成'*'否则会感染
                }
            }
        }
        int res=0;
        for(int i=1; i<=n; i++)
        {
            for(int j=1; j<=m; j++)
            {
              
                if(a[i][j]=='P') res++;
            }
        }
        printf("%d\n",res);
    }
    return 0;
}
另一种做法 找p旁白你有没有*又就不计算

丛林木马 数学题 找规律 高精度取模 这题卡了int 需要变成long long 检查了一个小时!!!

(*和%是从左往右算的)所以要及时加括号
res = res % mod + pre[i][j] % mod * a[i][j] % mod;
正确写法
res = res % mod + pre[i][j] % mod * (a[i][j] % mod);

#include<bits/stdc++.h>
#define int long long
const int mod=998244353;
const int N=1e5+10;
using namespace std;
char a[N],b[N];

signed main(){
    int t;   
    cin>>t;
    while(t--){
        string a,b;
        cin>>a>>b;   
        int x=0,y=0;
        for(int i=0;i<a.size();i++){
            x=x*10+a[i]-'0';  
            x=x%mod;
        }
        for(int j=0;j<b.size();j++){
            y=y*10+b[j]-'0';//将字符串变成long long 
            y%=mod;//每步都要取模不明白为什么这么做可以。。大概就是不影响???
        }
        cout<<((x*b.size())%mod+(y*a.size())%mod)%mod<<endl;//每次乘 或 加 后面都要取模。
    }
    return 0;
}


计算如果让你算1+2+…+n的值(由于答案可能很大,输出结果请对1e9+7取)
n的取值范围是1 ~ 1 0 10000 10^{10000}10
10000
那显然如果你在中间过程中不先取mod,必然会爆数据范围,因为不管是int还是long long甚至是double(最大约1 0 308 10^{308}10
308
)都无法存下这个数据所以中间部分需要取模

...
long long res = 0;
for(int i = 1; i <= n ; i ++) {
  //res = res + i;  
  res = (res + i) % (1e9 + 7); // n巨大,res无法存下这个数据
}
return res;


绝命杀虫 模拟的卡精度问题 将拿到倍率就将倍率*10 然后再算(如-1变成-10)前面再除个10

using namespace std;
typedef long long ll;
ll n,t,ans,inf = 10000;
double m;
int main()
{
    cin>>t;
    while(t--){
        cin>>n>>m;
        ans=0;
        ll num = n,a=0,b=0;//a是红,b是绿
        ll mm=m*10;
        while(num){
            a=num*100;
            //b=min(inf,num*100*(mm-1))错误答案
            b=min(inf,num*10*(mm-10));
            ans+=floor(a/10);
            ans+=floor(b/10);
            num=floor(a/200);
        }
        cout<<ans<<endl;
    }
    return 0;
}

变异蛮牛 数学找规律给黑点 给一棵树遍历点

那些样例解释要求区间 但是答案只有一个数字的很有可能是找规律 用排列组合计算

//求黑-百最多的树
#include<bits/stdc++.h>
#define int long long
using namespace std;

const int N=2e5+10;
int n,m,nums;
vector<int>v[N];
bool vis[N];
void dfs(int u,int high){
    if(vis[u]) return ; 
    vis[u]=true;
    if(high&1){
            nums++;
    } 
    for(int i=0;i<v[u].size();i++){
        int next=v[u][i];
        
        dfs(next ,high+1 );
        
    }      
}


signed main(){ios::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);
    int t;
    cin>>t;
    while(t--){
        cin>>n;
        int a,b;
        for(int i=1;i<=n;i++) {
            v[i].clear();
            vis[i]=0;//这里记得清空 方便下一组数据
        }
        
        for(int i=0;i<n-1;i++){
            cin>>a>>b;
            v[a].push_back(b);
            v[b].push_back(a);
        }//图的输入
        nums=0;
        dfs(1,1);
        
        cout<<nums*(nums+1)/2;
        cout<<endl;
    }
       
    return 0;
}

最小结果 四个操作数 三个操作符*和+ 要求最终生成最小的数

//直接新建一个容器 用这个容器进行下一步递归
//i,j用于选择数据
坑点//坑点有0
//不能交换操作符
//会爆int
//爆搜
直接dfs 画出递归搜索树 发现情况小 直接爆搜

include

include

include

include

define int long long

using namespace std;

char c[3];
int ans=1e18;

void dfs(vector v,int u ){
if(v.size()==1){
ans=min(ans ,v[0]); return ;//递归终点
}
for (int i = 0; i < v.size(); i ++ ){
for (int j = i+1; j < v.size(); j ++ ){//i,j用于选择数据
vector t;//直接新建一个容器 用这个容器进行下一步递归
for (int k = 0; k < v.size(); k ++ ){
if(k!=i&&k!=j) t.push_back(v[k]);

        }
        if(c[u]=='*') t.push_back(v[i]*v[j]);
        else t.push_back(v[i]+v[j]);
        
        dfs(t,u+1);
    }
}

}
signed main(){vectora(4) ;
for (int i = 0; i < 4; i ++ ) cin>>a[i];
for (int i = 0; i < 3; i ++ ) cin>>c[i];

dfs(a,0);
cout << ans;


return 0;

}

三元组 两个序列s c 找满足 si<sj<sk的i j k 能构成和最小的ci cj ck 的值的大小

三个 元素 i j k
固定 中间的j进行遍历 那么只要选择i在j 的左边和i在j的右边 的数进行操作就可以了

#include <iostream>
#include <cstring>
#include <algorithm>
#define int long long
const int N = 3e3+10,inf=5e8;
using namespace std;


signed main(){
    int n;cin>>n;
    int s[N],c[N];
    for (int i = 0; i < n; i ++ ){
        cin>>s[i];
    }
    for (int i = 0; i < n; i ++ ) cin>>c[i];
    
    int res=inf;
    for(int j=0;j<n;j++){
        int left =inf ;
        for(int i=0;i<j;i++){
            if(s[i]<s[j]) left=min(left,c[i]);
        }
        int right=inf;
        for (int i = j+1; i < n; i ++ ){
            if(s[i]>s[j])
                right=min(right,c[i]);
        }
        res=min(res,left+c[j]+right);
    }
    
    if(res==inf) cout<<"-1";
     else    cout<<res<<"\n";        
    return 0;
}

春季赛

牛牛学走路 签到题 根据坐标 找 需要PII

易错 分离开了x和y 应该把他看成坐标 把每个坐标看成集合

#include<bits/stdc++.h>
#define int long long
using namespace std;
#define x first
#define y second
typedef pair<int,int>  PII;

char c[1005];

PII q[1005];
signed main(){int t;cin>>t;
    while(t--){
        int x1=0,x2=0,y1=0,y2=0;
        double res=0;
        int n;cin>>n;
        scanf("%s",c);
        int xmax=0;
        int ymax=0;
        for(int i=0;i<sizeof(c);i++){
            if(c[i]=='L') x1++;
            else if(c[i]=='R') x1--;
            else if(c[i]=='U') y1++;
            else if(c[i]=='D') y1--;
//             x=max(x,abs(x1));
//             y=max(y,abs(y1));
            q[i]={abs(x1),abs(y1)};
        }
        
        for(int i=0;i<n;i++){
        int xx=q[i].x ,yy=q[i].y;
            res=max(res  , sqrt((double)((int)(abs(xx*xx+yy*yy)+0.00000000000001))) ) ;//二维坐标用pii
        }
        
        

        printf("%.12lf",res);
        cout<<endl;
    }
    
    
    
    return 0;
}

中位数 数学找规律 类似于树重心 总之只要一边满足就可以了

#include<bits/stdc++.h>
#define int long long
using namespace std;
const  int N=1e5+10;
int a[N];
signed main(){int t;cin>>t;
    while(t--){
        int n,m;
        cin>>n>>m;
        for(int i=1;i<=n;i++) 
        cin>>a[i];
        sort(a+1,a+1+n);int y;
        for(y=1;y<=n;y++)   
        if(a[(int)((ceil)(y/2.0))]>=m) break;
        if(y==n+1) cout<<-1;
        else cout<< n-y+1;
        cout<<endl;
    }
     
    return 0;
}

小朋友做游戏 模拟 按照幸福值排序 选 选完最多的b就不能选 环的性质 发现规律 b不超过所有的一半

//不能b紧紧挨着 选择n个人
//a可以紧紧挨着
//对v排序
#include<bits/stdc++.h>
#define int long long
using namespace std;
typedef pair<int ,int > PII;
#define x first
#define y second 
const int N=2e5+10;

signed main(){int t;cin>>t;
    while(t--){
        PII q[N];
       int a,b,n;cin>>a>>b>>n;
        int c;
       for(int i=0;i<a;i++){
           cin>>c;
           
           q[i]={c ,'a'};
       } 
           
       for(int j=a;j<a+b;j++){
           cin>>c;
           q[j]={c ,'b'};
       }
//         for(int i=0;i<a+b;i++) cout<<q[i].x;cout<<endl;
        sort(q,q+a+b,greater<PII>());
        
        int bmax=n/2,sum=0;
        if(a<n-bmax){
            cout<<-1<<endl;
            continue;
        }
        for(int i=0;;i++) {
            if(n==0) break;
            if(q[i].y=='a'){
                sum+=q[i].x ;n--;
                
            }
            
            else if(q[i].y=='b' &&bmax){
                sum+=q[i].x;n--;
                bmax--;
            }
        }
        if(sum==0) cout<<"-1";
        else cout<<sum;
        
        cout<<endl;
    }
    

    return 0;
}

炸鸡块君的高中回忆 找数学的浮点数

不知道原来ceil也会有精度缺失 需要+0.000001取整

#include<bits/stdc++.h>
#define int long long
using namespace std;

signed main(){int t;cin>>t;
    while(t--){
        int a,b,ans=0;
        cin>>a>>b;
        if(a!=1&&b==1) {
            cout<<-1<<endl;
            continue;
        }
        
        if(a>b){
            cout<<(int)((ceil)((double)(a-b)/(b-1))+0.0000000001)*2+1 ;
        }
        
        else cout<<1;


        
        
        cout<<endl;
    }
    
 
    return 0;
}

牛牛看云

一开始以为找规律 ,结果有绝对值 无法去掉 绝对值
那就只好拿出来算
因为数据范围小 0<a[i]<1000 所以两层for遍历也没关系
多画几个图 如 1 2 3 和 1 2 2 3 和 1 2 2 2 3 和1 1 2 2 2 3 慢慢可以发现
除了相同数字相加的部分 ,如1+2 算了1=11 2=12 3=13 6=12次 所以需要记下来各个数字出现了多少次 该条算式出现了b[i]b[j]
对于相同部分 一开始以为是对角线 但对比数据发现 出现了 一个三角形的区域 所以应该是等差数列 如出现4次 则 4+3+2+1 即(n+1)
n/2次

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e6+10;int b[N];
signed main(){int n;cin>>n;
    int sum=0,a;int m=1000;
    for(int i=0;i<n;i++) {
        cin>>a;
        b[a]++;
    }              
    for(int i=0;i<=1000;i++){
        for(int j=i;j<=1000;j++){
            if(i==j){
                sum+=abs(i+i-m)*(b[i]+1)*b[i]/2;
            } 
             else {
                 sum+=abs(i+j-m)*b[i]*b[j];
             }
        }
    }
              cout<<sum;
 
    return 0;
}



COW dp状态机 抽象成 记录当前状态 对每个字符确定 状态并且对a[]的值增加 那么最后一个状态的数量答案才是想要的结果

根据值包含cow的字符串 找到可能构成字符串COW的数字

#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;

const int N = 1e5+10;
int main()
{   long long  a[3];
    int n;cin>>n;char c[N];
    for(int i=0;i<n;i++){
        cin>>c[i];
        if(c[i]=='C') a[0]++;//
        else if(c[i]== 'O') a[1]+=a[0];//到达这个状态 就直接加上一个值
        else a[2]+=a[1];
    }

    cout<<a[2];
    return 0;
}

贝茜放慢脚步 走路走到距离b[]和时间t[i]会减速 问走到终点需要多少时间

二路归并 一个while两个情况 至一种情况使用完

#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;

vector<int> a,b;
const int N = 1e5+10;
int main(){int n;cin>>n;
    for (int i = 0; i < n; i ++ ){int d;char c[2];
        scanf("%s%d", c, &d);
        if(c[0]=='T') a.push_back(d);
        else b.push_back(d);
    }
    b.push_back(1000);double t=0,s=0,v=1;
    sort(a.begin( ),a.end());
    sort(b.begin() ,b.end());
    int i=0,j=0;//用i和j遍历数组下标
    while(i<a.size()||j<b.size()){
        
        if(j==b.size()||i< a.size() && a[i]-t<(b[j]-s )*v){//减速点走完的时候或者 时间点减速的
            
            s=s+(a[i]-t)/v;//因为v是速度的倒数 所以这里用乘
            t=a[i];
            v+=1;
            i++;
        }else{
            
            t+=( b[j]-s )*v;
            s=b[j];
            v+=1;
            j++;
        }

    }
    
    printf("%.0lf",t);
    return 0;
}

| 作为对萌新《友好》的寒假集训营,小红当然要送给大家一道签到题! |

| --------------------------------------- |
| 小红拿到了一份代码: |
| |
| 1 |
| 2 |
| 3 |
| 4 |
| long long f(long long x){ |
| if(x==1)return 1; |
| return f(x/2)+f(x/2+x%2); |
| } |
| |
| |
| |
| 给定一个正整数 xx ,她希望你能输出 f(x)f(x) 的值,你能帮帮她么? |

打表题 打表可以发现 自己的fx=x的规律

long long f(long long x){
    if(x==1)return 1;
    return f(x/2)+f(x/2+x%2);
}
signed main(){
    int n;
    for(int i=1;i<100;i++)
    cout<<f(i)<<endl;
    return 0;
}```
posted @ 2022-01-22 14:58  liang302  阅读(34)  评论(0编辑  收藏  举报