私人笑声:
知识点一:EOF
在while循环中以EOF作为文件结束标志,这种以EOF作为文件结束标志的文件,必须是文本文件。在文本文件中,数据都是以字符的 ASCII 代码值的形式存放。我们知道,ASCII代码值的范围是0~255,不可能出现-1,因此可以用EOF作为文件结束标志。
如果scanf()函数全部正常读取,它就返回几。
while((scanf"%d,%d",&m,&n)==2)
while((scanf"%d,%d",&m,&n)!=EOF)
输入空格的几种方法:
1,string a;
getline(cin.a);
2, char a[N];
cin.getline(a,num);
3.gets一般不能用
#include<bits/stdc++.h>
using namespace std;
const int N = 1e6+10 ;
int n , v[N] ;
char s[N];
string o;
string ans;
int main(){
while((scanf("%s",&s))!=EOF){
int u=strlen(s);
for(int i=0;i<u;i++){
if(s[i]=='.'){
cout<<s[i]<<"xixixixi";
}
cout<<s[i];
}
cout<<" ";
}
return 0;
}
该加训啦:
位运算:1&(与):只有两位数字都是1,结果才为1,否则为0;
2 |(或):有至少一个1,结果就为1;
2 ^ (异或):相同位数字相同则为0,不同就为1;
3~(取反):略;
4 << (左移);<<<(无符号左移)
5 >>(右移):>>>(无符号右移)
常用公式:a^0=a (任何数异或0是它本身)
a^a=0 (两个相同的数异或和为0)
a^(b^c)=(a^b)^c;(异或和满足结合律)
a^b=b^a;(异或和满足交换律)
a | 0=a(一个数或0还是这个数)
a | ~ a =1;
a | a = a;
a | ( b | c )=( a | b ) | c;
a | b = b | a;
a & 0=0;
a&~a=0;
a&a=a
一样满足交换律和结合律;
列出4种情况,观察可知(a&b)^(a|b)=a^b;
用前缀异或和记忆化储存
因为r^r=0;
a^0=a;
所以可以让最终的前缀和 ^ (l-1)之前的前缀和,(l-1)就全为0了,就可以得到最终的答案;
代码:
#include <bits/stdc++.h>
using namespace std;
#define PII pair<int,int>
#define int long long
int x[200005],sum[200005];
signed main(){
int n,m;
cin>>n;
for(int i=1;i<=n;i++){
cin>>x[i];
}
for(int i=1;i<=n;i++){
sum[i]=sum[i-1]^x[i];
}
cin>>m;
for(int i=0;i<m;i++){
int l,r;
cin>>l>>r;
cout<<(sum[r]^sum[l-1])<<endl;
}
return 0;
}
奶茶袋收集
要找出最小的极差和:
一组里面的最大值-最小值=相邻两数的差值之和
所以计算所有相邻两数的差值之和
因为要分成m段,就有m-1个差值不在极差和里;
减掉即可;但要求极差和最小,所以对每个差值排序,
依次减去最大的差值就好
#include <bits/stdc++.h>
using namespace std;
#define int long long
int a[100005],sum=0;
int b[100005];
signed main()
{
int n,m;
cin>>n>>m;
for(int i=1;i<=n;i++){
cin>>a[i];
}
sort(a+1,a+1+n);
for(int i=2;i<=n;i++){
int x;
b[i-1]=a[i]-a[i-1];
sum+=b[i-1];
}
sort(b,b+n);
int cha=0;
for(int i=n-1,k=0;k<m-1;i--,k++){
cha+=b[i];
}
int ans=sum-cha;
cout<<ans;
return 0;
}
基于文化课的算法学习:
此题注意find_first/last_of的用法:(错用成查找第一次出现此字符串的位置)
find找不到时返回-1!不是0!;
转载:
#include <bits/stdc++.h>
using namespace std;
string a,b,c="zxz",d;
string q,aa="main";
string bb="return";
int n,k,x;
int mm,ee;
int main(){
cin>>n;
cin>>b>>a;
d=a;
if(a.find(aa)==-1||a.find(bb)==-1){
cout<<"wrong"<<endl;
return 0;
}
else{
mm=a.find(aa);
ee=a.rfind(bb);
while(a.find(b)!=-1){
x=a.find(b);
for(int i=x,k=0;k<3;i++,k++){
a[i]=c[k];
}
}
for(int i=mm;i<=ee;i++){
a[i]=d[i];
}
cout<<a;
}
return 0;
}
红石信号源 :
红石之间的连接顺序是根据输入顺序决定的,并且能量传递是沿着红石线路传递的,传递的时候只能沿着线往前传或者往后传,可以将连接所有红石的二维图转换成一维的数轴;
注意:第一个点不一定是1=(0,0)!!!!;
一颗红石信号源能让d颗红石能量值大于等于m;
d=(15-m)*2+1;(红石信号源向两端传递能量,+1是它自己本身的颗数)
以d为一个周期,总共有sum长度。则最后结果为sum/d,
若sum%d有余数,则还需要一颗红石信号源
#include<bits/stdc++.h>
using namespace std;
#define int long long
int n,m,sum=1;
int x[200010],y[200010];
signed main(){
cin>>n>>m;
x[0]=0;
y[0]=0;
for(int i=1;i<=n;i++){
cin>>x[i]>>y[i];
if(i!=1)sum+=abs(x[i-1]-x[i])+abs(y[i-1]-y[i]);
}
int d=(15-m)*2+1;
int ans=sum/d+(sum%d?1:0);
if(m==0)cout<<0<<endl;
else cout<<ans<<endl;
return 0;
}
cy的倒金字塔工厂:
模拟题:
题意流水线上不为空时,若半成品中没有东西,直接放入即可,若有东西,半成品中最上面的长度小于将要放上来的长度,并且长度差不超过规定的m,就可以直接放入半成品中,若没有满足条件,查找盒子上第一个块的长度满不满足长度,若满足,将其提取出来,放入半成品中,将不满足的块放入盒中。
#include <bits/stdc++.h>
using namespace std;
#define int long long
int n,m;
signed main()
{
cin>>n>>m;
stack<int>a;
stack<int>box;
stack<int>half;
queue<int>rub;
for(int i=0;i<n;i++){
int x;
cin>>x;
a.push(x);
}
while(!a.empty()||!box.empty()){
while(!a.empty()){
if(half.empty()){
half.push(a.top());
a.pop();
}
else {
if(a.top()>half.top()&&a.top()-half.top()<=m){
half.push(a.top());
a.pop();
}
else{
if(!box.empty()&&box.top()>half.top()&&box.top()-half.top()<=m){
half.push(box.top());
box.pop();
}
box.push(a.top());
a.pop();
}
}
}
if(a.empty()){
if(half.size()>=2){
while(!half.empty()){
cout<<half.top()<<" ";
half.pop();
}
cout<<endl;
}
else {
rub.push(half.top());
half.pop();
}
stack<int>t;
while(!box.empty()){
t.push(box.top());
box.pop();
}
while(!t.empty()){
a.push(t.top());
t.pop();
}
}
}
while(!rub.empty()){
cout<<rub.front()<<" ";
rub.pop();
}
return 0;
}
swj学长的精灵融合:
低级精灵:1 2 4 7 11;(第二个在第一个的基础上加1,第三个在第二个的基础上加2,第四个在第三个的基础上加三,以此类推);
中级精灵:1 3 7 13 21;(第i个在i-1的基础上加2*(i-1))
高级精灵:1 6 16 31 51;(第i个在i-1的基础上加5*(i-1));
全都是0:
题意是只减数位上的任意一个数,不是任意减,并且比如16,16-6=10,此时10减的是10上对应数位的数字,不在是16数位上对应的数字;
#include<bits/stdc++.h>
using namespace std;
int v[1000006],ans;
int main(){
string n;
cin>>n;
while(1){
ans++;
int l=n.size();
for(int i=0;i<l;i++){
v[i]=n[i]-'0';
}
sort(v,v+l);
int y=stol(n);
n=to_string(y-v[l-1]);
if(y-v[l-1]<10)break;
else if(y-v[l-1]==10){
ans+=2;
break;
}
}
cout<<ans;
return 0;
}
相加余三:
此题是选一种操作一直操作才去,不是都可以选!!!
只需要将三种操作分别算一遍,求最大值即可;
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> PII;
const int N = 2e5+10;
ll n, m, k,max1;
int a[2005];
ll ff1(int n,int a[]){
int j=1,b=n,num=0;
while(b<=n){
num+=(a[j]+a[b])%3;
j+=2;
b+=2;
}
return num;
}
ll ff2(int n,int a[]){
int j=n-1,b=n,num=0;
while(j>=1){
num+=(a[j]+a[b])%3;
j-=2;
b-=2;
}
return num;
}
ll ff3(int n,int a[]){
int j=1,b=n,num=0;
while(b>j){
num+=(a[j]+a[b])%3;
j++;
b--;
}
return num;
}
void sovle(){
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
}
max1=max(ff1(n,a),max1);
max1=max(ff2(n,a),max1);
max1=max(ff3(n,a),max1);
cout<<max1;
}
int main()
{
ios::sync_with_stdio(false), cin.tie(0),cout.tie(0);
int t = 1;
while (t --){
sovle();
}
return 0;
}
□□,□□!
输出签到题:
#include <bits/stdc++.h>
using namespace std;
#define int long long
signed main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout<<"yuan shen, qi dong!";
return 0;
}
比较大小
数学图像,其中当x=1时为零界点
#include <bits/stdc++.h>
using namespace std;
#define int long long
signed main()
{
ios::sync_with_stdio(0);
cin.tie(0);
double x;
cin>>x;
if(x>1)cout<<">";
else if(x==1)cout<<"=";
else cout<<"<";
return 0;
}
基于金铲铲的期望学习
读题带公式就可以了
#include <bits/stdc++.h>
using namespace std;
#define int long long
signed main()
{
double x;
cin>>x;
if(x<=8){
double y=2;
printf("%.2f",y);
}
else {
int f=x+8;
double ans=1+8.0/x;
printf("%.2f",ans);
}
return 0;
}
奇怪的克制倍数
仔细读题就能做
#include <bits/stdc++.h>
using namespace std;
#define int long long
signed main()
{
double a,b,c,d,ans1,ans2,ans;
cin>>a>>b>>c>>d;
if(a==0||b==0){
ans1=(a+b)/4.0;
}
else if(a==2&&b==2)ans1=a+b;
else {
ans1=(a+b)/2.0;
}
if(c==0||d==0){
ans2=(c+d)/4.0;
}
else if(c==2&&d==2)ans2=c+d;
else {
ans2=(c+d)/2.0;
}
ans=(ans1+ans2)/2.0;
printf("%.6f",ans);
return 0;
}
加纳~
#include<bits/stdc++.h>
using namespace std;
const int N = 1e6+10 ;
int n , v[N] ;
char s;
string ans;
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int n,m,k;
cin>>n>>m>>k;
int y=k/n;
int u=k%n;
if(u>=m){
y++;
}
cout<<y;
return 0;
}
找除数
约数考点:任何正整数都可以写成质数的几次方相乘的形式
n=p1^x∗p2^y∗p3^z……,是素数,n的除数的数量就=(x+1)(y+1)(z+1).....;
约数等于(次方+1)相乘,至于为什么+1;
举一个例子:12=2^2+3;
约数=1*2*2 * 1*3;(质因子本身也是一个除数)
此题目中还用到了线性筛,可以很快找到谁是质数。
#include <bits/stdc++.h>
using namespace std;
#define PII pair<int,int>
int prime[1000005];
int flag[1000005];
int cnt=0;
void get_prime(int x){
for(int i=2;i<=x;i++){
if(flag[i]==0){
prime[cnt++]=i;
}
for(int j=0;i*prime[j]<=x;j++){
flag[i*prime[j]]=1;
if(i%prime[j]==0){
break;
}
}
}
}
int main(){
ios::sync_with_stdio(0);
cin.tie(0);
int t,n;
get_prime(100000);
cin>>t;
while(t--){
cin>>n;
vector<int>g;
for(int i=0;prime[i]<=n/prime[i]&&i<cnt;i++){
int y=0;
while(n%prime[i]==0){
y++;
n/=prime[i];
}
if(y){
g.push_back(y);
}
}
if(n>1)g.push_back(1);
int ans=1;
for(auto l: g){
ans=ans*(l+1);
}
cout<<ans<<endl;
}
return 0;
}