- 跳跳
求两个位置之间的gcd,时间复杂度过高;
简化:dx与dy之间先求最大公因数【把一步最简化的过程】+ 去重【set】
#include<bits/stdc++.h>
using namespace std;
set< pair<long,long> >s;
const int maxn=1e5;
long x[maxn];
long y[maxn];
int main()
{
int n;cin>>n;
int sum=0;
for(int i=1;i<=n;i++)
{
cin>>x[i]>>y[i];
}
for(int i=1;i<=n;i++)
{
for(int j=i+1;j<=n;j++)
{
long dx=abs(x[i]-x[j]);
long dy=abs(y[i]-y[j]);
long k=__gcd(dx,dy);
s.insert(make_pair(dx/k,dy/k));
}
}
cout<<s.size()*2;
return 0;
}
int gcd(int x,int y)
{
return b?gcd(b,a%b):a;
}
-
异或和或
留意细节,理清思路
- 0 1-1 1、1 0- 1 1、0 0- 0 0、1 1-1 0、1 0- 0 1【两步变换】
- 1变成0 条件 存在 1 1或者0 1
- 0变成1 条件存在1 1 或者1 0
#include<iostream> using namespace std; int main() { int t;cin>>t; while(t--) { string s; string t; cin>>s>>t; int ls=s.size(); int lt=t.size(); int s00=0,s01=0,s10=0,s11=0; if(ls!=lt) cout<<"NO"; else{ for(int i=0;i<ls;i++) { if(s[i]=='1'&&t[i]=='1') { s11++; } if(s[i]=='1'&&t[i]=='0') { s10++; } if(s[i]=='0'&&t[i]=='0') { s00++; } if(s[i]=='0'&&t[i]=='1') { s01++; } } if((s10>0&&(s11==0&&s01==0))||(s01>0&&(s11==0&&s10==0))) cout<<"NO"; else cout<<"YES"; } cout<<endl; } }
-
01序列
- 注意分类:k==0需要单独讨论
- k!=0的时候根据前导0与后置0求答案【仔细分析,数学问题】
- 子串得是相连的!!不是2^n
- 求前导0 与 后置0 方法
- 用vector储存1的位置
- 双指针
#include<bits/stdc++.h> using namespace std; vector<long long>v; int main() { long long k; cin>>k; string s; cin>>s; v.push_back(0); for(long long i=0;i<s.size();i++) { if(s[i]=='1') v.push_back(i+1); } v.push_back(s.size()+1); long long sum=0; long long l=v.size(); if(k<v.size()&&k!=0) { for(long long i=1;i<l-k;i++) { long long x=v[i]-v[i-1]; long long y=v[i+k]-v[i+k-1]; sum+=x*y; } } else if(k==0) { for(long long i=1;i<l-k;i++) { long long x=v[i]-v[i-1]-1; sum+=x*(x+1)/2; } } else if(k>v.size()) sum=0; cout<<sum; return 0; }
-
加一:!
- 又被cin 和cout 卡了!
- 利用动态规划:f[i] [j]表示第i次操作时该数位为j的个数
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e9+7;
const int x=200050;
long long f[x][10]={0};
int main()
{
int t;
scanf("%d",&t);
for(int i=0;i<=9;i++) f[0][i]=1;
for(int i=1;i<=x;i++)
{
for(int j=1;j<=9;j++) f[i][j-1]=f[i-1][j];
f[i][9]=(f[i-1][1]+f[i-1][0])%maxn;
}
while(t--)
{
char a[20];
int m;
long long ans=0;
scanf("%s %d",&a,&m);
int l=strlen(a);
//统计所有数的个数
for(int i=0;i<l;i++)
{
ans+=f[m][a[i]-'0'];
ans%=maxn;
}
printf("%d\n",ans);
}
return 0;
}
- 整齐的数组:求一组数的最大公因数:ans记录此时的最大公因数;思想就是所有数的公因数一定是某两个数的公因数
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=1e6;
int main()
{
int t;cin>>t;
int a[100]={0};
while(t--)
{
int n;
cin>>n;
int flag=0;
for(int i=1;i<=n;i++) {
cin>>a[i];
}
for(int i=1;i<=n;i++)
{
if(a[i]!=a[1])
{
flag=1;
break;
}
}
sort(a+1,a+1+n);
int ans=0;
if(flag==0) cout<<"-1"<<endl;
else
{
//求数组中所有数的公因数
for(int i=2;i<=n;i++)
{
if(a[i]!=a[1])
{
ans=__gcd(ans,a[i]-a[1]);
}
}
cout<<ans<<endl;
}
}
return 0;
}
- 网格判断
- 分别罗列 行和列
- 简单的模拟
#include<iostream>
using namespace std;
int main()
{
int n;
cin>>n;
int a[30][30];
for(int i=1;i<=n;i++)
{
int s1=0,s0=0;
for(int j=1;j<=n;j++)
{
char x;
cin>>x;
if(x=='W')
{
a[i][j]=1;
s1++;
}
else {
a[i][j]=0;
s0++;
}
}
if(s1!=s0)
{
cout<<"0";
return 0;
}
}
for(int j=1;j<=n;j++)
{
int s1=0;int s0=0;
for(int i=1;i<=n;i++)
{
if(a[i][j]==1) s1++;
else s0++;
}
if(s1!=s0)
{
cout<<"0";
return 0;
}
}
int x=0,s=0;
for(int i=1;i<=n;i++)
{
x=0;s=0;
for(int j=1;j<=n;j++)
{
if(a[i][j]!=x)
{
x=a[i][j];
s=1;
}
else {
s++;
}
if(s>=3)
{
cout<<"0";
return 0;
}
}
}
for(int j=1;j<=n;j++)
{
x=0;
s=0;
for(int i=1;i<=n;i++)
{
if(a[i][j]!=x)
{
x=a[i][j];
s=1;
}
else {
s++;
}
if(s>=3)
{
cout<<"0";
return 0;
}
}
}
cout<<"1";
return 0;
}
- 出栈序列判断
- stack的应用
- 遇到相同的数就pop
- 不相同就push
#include<iostream>
#include<stack>
using namespace std;
const int maxn=1e6;
stack<int>s;
int a[maxn];
int main()
{
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
int k=1;
for(int i=1;i<=n;i++)
{
s.push(i);
printf("push %d\n",i);
while(!s.empty()&&s.top()==a[k])
{
s.pop();
printf("pop\n");
k++;
}
}
return 0;
}
- 序列维护
- 可以手写链表
- 也可以用stl中的list
#include<bits/stdc++.h>
using namespace std;
int main()
{
int m;cin>>m;
list<int>q;
while(m--)
{
string b;
cin>>b;
//在某个位置插入
if(b[0]=='i')
{
int x,y;
cin>>x>>y;
list<int>::iterator it=q.begin();
if(x==0) q.insert(it,y);
else {
while(x)
{
it++;
x--;
}
q.insert(it,y);
}
}
//删除
else if(b[0]=='d')
{
int x;cin>>x;
list<int>::iterator it=q.begin();
while(x-1)
{
it++;
x--;
}
q.erase(it);
}
//查询
else
{
int x;cin>>x;
list<int>::iterator it=q.begin();
while(x-1)
{
it++;
x--;
}
cout<<*(it)<<endl;
}
}
return 0;
}
- 饿饿饭饭
- 一开始的思路是最小公倍数是2m+3k 时间复杂度过大
- 通过数学公式变化 可以变成除以最大公因数能否变成2m+3k 形式
#include<bits/stdc++.h>
using namespace std;
int main()
{
int t;
cin>>t;
while(t--)
{
int n;cin>>n;
int a[100005];
for(int i=1;i<=n;i++) cin>>a[i];
int ans=a[1];
for(int i=1;i<=n;i++)
{
ans=(ans,__gcd(ans,a[i]));
}
int flag=0;
for(int i=1;i<=n;i++)
{
int m=a[i]/ans;
while(m%2==0)
{
m/=2;
}
while(m%3==0)
{
m/=3;
}
if(m!=1) {
flag=1;
break;
}
}
if(flag==0) cout<<"YES";
else cout<<"NO";
cout<<endl;
}
return 0;
}