寒假的比赛题
对于多组输入样例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
ZPPZ
#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
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
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(){vector
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;
}```