判断是否全是顺时针或者全是逆时针顺序。
不是第一个人或者最后一个人的时候,后一个人与前一个人之差要么为+1,要么为-1;如果是开头结尾则为n-1或者1-n。判断输入的第一个人和第二人之差,f=p[1]-p[0],如果f绝对值不为1,看f绝对值是否为n-1,都不是那肯定不对。
当f为n-1的时候,队列一定是逆时针,p[i]-p[i-1]=-1(i!=1&&i<n)
当f为1-n的时候,队列一定是顺时针,p[i]-p[i-1]=1.(i!=1&&i<n)
当f为-1的时候,队列一定是逆时针,p[i]-p[i-1]=-1.,存在1次n-1(i<n)
当f为1的时候,队列一定是顺时针,p[i]-p[i-1]=1.,存在1次1-n(i<n)
然后再去判断剩下所有人即可。注意n-1或1-n这种情况只会出现一次,剩下一定是1或-1
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <cmath>
#include <queue>
using namespace std;
int p[205];
int main()
{
int q,n,f=0;
cin>>q;
while(q--)
{
cin>>n;
int cnt=0;
bool flag=true;
memset(p,0,sizeof(p));
for(int i=0;i<n;i++)
cin>>p[i];
f=p[1]-p[0];
if(f!=1&&f!=-1)
{
if(abs(f)!=n-1)
flag=false;//绝对值不等于1或n-1一定错
else
{
if(f>0)
f=-1;
else
f=1;
}
}
for(int i=1;i<n&&flag;i++)
{
if(p[i]-p[i-1]!=f)
{
if(abs(p[i]-p[i-1])==n-1&&(p[i]-p[i-1])*f<0&&cnt==0)//n-1对应-1,1-n对应n,相乘一定小于0
{
cnt=1;//出现过一次就不能再出现了
continue;
}
else
{
flag=false;
break;
}
}
}
if(flag) cout<<"YES"<<endl;
else cout<<"NO"<<endl;
}
}
给你4*n条边,能否组成n个面积大小相同的矩形。
矩形只用考虑两条边即可。一定当前最大边和最小边结合。假设不是当前最小边和最大边(边长不重复)结合,那么最小边lmin和边l1(非最大边)结合得到面积s1的矩形,那么最大边lmax与边2(非最小边)结合得到面积为s2的矩形,
s1=lmin*l1
s2=lmax*l2
因为l1<lmax,lmin<l1
则s2>s1
所以排序后,每次让最大边和最小边结合即可。另外注意当前最小边前面的边大小一定等于最小边,最大边后面的一定要等于最大边,要不然构不成矩形。
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <cmath>
#include <queue>
using namespace std;
int s[405];
int main()
{
int q,n;
cin>>q;
while(q--)
{
cin>>n;
for(int i=0;i<4*n;i++)
cin>>s[i];
sort(s,s+4*n);
int cnt=0,sm=s[0]*s[4*n-1];
bool flag=true;
for(int i=0;i<=2*(n-1);i+=2)
{
int last=4*n-1-i;
if(s[i+1]!=s[i]||s[last]!=s[last-1]||s[i]*s[last]!=sm)
{
flag=false;
break;
}
}
if(flag) cout<<"YES"<<endl;
else cout<<"NO"<<endl;
}
}
求能被当前所有数字整除的数的个数。
求最大公因数的因子数。gcd之后暴力求即可。注意这种涉及因子的问题,
1要特判,完全平方数要特判。
经过zyy大佬的点拨,1不会进sqrt的循环,在完全平方数的时候会判断到它。
另外第一次写完全平方数的特判的时候,竟然用n%sqrt(n)==0来判,真是失了智。
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <cmath>
#include <queue>
#define LL long long
using namespace std;
LL q[400010];
LL gcd(LL a,LL b)
{
if(b==0)
return a;
if(a<b)
return gcd(b,a);
return gcd(b,a%b);
}
int main()
{
int n;
cin>>n;
LL g,num=0;
for(int i=0;i<n;i++)
{
cin>>q[i];
if(i==0)
g=q[i];
else
g=gcd(g,q[i]);
}
if(g==1)//1的特判
cout<<"1";
else
{
for(LL i=1;i<sqrt(g);i++)
if(g%i==0)
num+=2;
LL i=sqrt(g);//完全平方数特判
if(i*i==g) num++;
cout<<num;
}
}
这题我不知道暴力怎么写。。。当时直接跳了,其实已经有了想法,但我的想法是基于子字符序列的字母,而不是子字符序列,重复的时候无法还原子字符序列,觉得不可做,就跳了,最后发现自己弱智了,基于子子字符序列考虑,它的字母根本不重要。
找出子字符序列在母字符串第一次出现的的时候每一位的下标,和最后一次出现每一位的下标,删除的话只能删除第一个字母之前,两个相邻字母之间,最后一个字母之后这三种情况。
举个例子
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | |
k | a | s | k | j | d | g | a | j | k | s | a | g | d | |||||||
a | s | d | ||||||||||||||||||
第一次出现的位置 | a | s | d | |||||||||||||||||
最后一次出现的位置 | a | s | d |
删除头的情况,最后一次出现asd的时候,a的下标是7,代表从头删的时候,这个地方的a不能删,否则无法构成asd了。注意不是最后一次出现a的11位置,要保证可以组成asd。那么7前面的都可以删。
删除尾的情况,第一次出现asd的d是在5,代表从尾删的时候,这个位置的d不能删,否则就无法构成asd了。
在中间删除的情况,比如删除sd中间,那最大值就是s第一次出现与d最后一次出现之间的长度,再往前或往后延伸就构不成asd了。
所以从后往前扫一遍母串,找到子序列各位在母串最后一次出现的位置,再从前往后扫一遍,找到第一次出现的位置。然后维护最大值即可。
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <cmath>
#include <queue>
#include <string>
#include <vector>
#define LL long long
using namespace std;
int fp[200010],lp[200010];//fp是第一次出现的时候,lp是最后一次出现的时候
bool f[30];
int main()
{
string s1,s2;
cin>>s1>>s2;
int l1=s1.size(),l2=s2.size();
int cnt=l2-1;
for(int i=l1-1;i>=0&&cnt>=0;i--)
{
if(s1[i]==s2[cnt])
lp[cnt--]=i;//找到了后一位就开始找前一位
}
cnt=0;
for(int i=0;i<l1&&cnt<l2;i++)
if(s1[i]==s2[cnt])
fp[cnt++]=i;
int maxn=lp[0];
for(int i=1;i<=l2-1;i++)
maxn=max(maxn,lp[i]-fp[i-1]-1);
maxn=max(maxn,l1-1-fp[l2-1]);
cout<<maxn<<endl;
}
每个数可以加一或减一,但不能为0,问你不同的数最多有多少个。
每个数只能出现出现一次,那就看一下这个数+1,不变,-1的数字有没有出现过,没有就可以把他加上,而且一个数只能出现一次,所以谁去当这个数都是无所谓的。
但是注意比较的顺序!!!对于n,先看n+1出现过没有,再看n,最后看n-1。
比如4 4 4 5
就可以让5变成6,然后4变成5,4不变,4变成3,将它们都放进队列。因此WA了一发,哭死。
“谁去当这个数都是无所谓的”意思是
比如3 4 4 4
可以让4变成5,4不变,4变成3进队列,而不要3;和将4变成5,4不变,3不变放进队列是一样的。只要3,4,5这三个数有人即可。
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <cmath>
#include <queue>
#define LL long long
using namespace std;
int w[150010],num[150010];
int main()
{
int n,cnt=0;
cin>>n;
memset(w,0,sizeof(w));
for(int i=0;i<n;i++)
cin>>w[i];
sort(w,w+n);
for(int i=n-1;i>=0;i--)
{
if(num[w[i]+1]==0)
num[w[i]+1]++,cnt++;
else if(num[w[i]]==0)
num[w[i]]++,cnt++;
else if(w[i]-1!=0&&num[w[i]-1]==0)
num[w[i]-1]++,cnt++;
}
cout<<cnt<<endl;
}
总结:1、不要太急,想清楚了再写。
2、做专题做的脑子有点死,适当做些思维题活跃一下脑子。