1.连续自然数和(LuoguP1147)
题目描述:
对一个给定的自然数M,求出所有的连续的自然数段,这些连续的自然数段中的全部数之和为M。
例子:1998+1999+2000+2001+2002 = 10000,所以从1998到2002的一个自然数段为M=10000的一个解。
思路:
纯数学的水题,分两种情况进行讨论:把给定的数分为奇数份或将给定的数分为偶数份。当分为奇数份时,先检查时候能正好分为i份,如果能则确定中位数,并顺次确定头和尾。当分为偶数份时,找到中位数之前的那个数并找到头和尾。至于答案的顺序问题,只要从分的份数从多到少就可以保证首位数字从小到大(想一想,为什么)。
代码:
/*
2016.8.9 BulaBulaCHN
*/
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<string>
#include<cstring>
#include<iostream>
using namespace std;
int m;
int main()
{
freopen("combo.in","r",stdin);
freopen("combo.out","w",stdout);
scanf("%d",&m);
for(int i=m;i>=2;i--)
{
if(i%2==1)
{
int mid=m/i;
if(mid*i!=m) continue;
if(mid>=i/2) printf("%d %d\n",mid-i/2,mid+i/2);
}
else if(i%2==0)
{
double mid=(double)m/i;
if(mid-(int)m/i!=0.5000) continue;
int md=(int)mid;
if(md-i/2+1>=0) printf("%d %d\n",md-i/2+1,md+i/2);
}
}
fclose(stdin);
fclose(stdout);
return 0;
}
2.约瑟夫(LuoguP1145)
题目描述:
n个人站成一圈,从某个人开始数数,每次数到m的人就被杀掉,然后下一个人重新开始数,直到最后只剩一个人。现在有一圈人,k个好人站在一起,k个坏人站在一起。从第一个好人开始数数。你要确定一个最小的m,使得在第一个好人被杀死前,k个坏人先被杀死。
思路:
看到这个题想到的当然还是模拟了,因为第一眼看的时候数据范围只有14嘛……结果到11的时候我就(机智地)发现纯模拟肯定是T了。在这里我提供两种优化的思路:第一种,运用链表,可以迅速的进行删除操作,也省去了很多多余的数数操作;第二种,每删除一个点更新一下人数t,用当前位置+步数mod当前人数就是下一个被删除的人(比较快)。
代码:
#include<cstdio>
#include<iostream>
using namespace std;
int a[16];
bool fun(int k,int m)//确定两阵营各有k人步长为m时是否合法
{
int s=0;
int t=2*k;
for(int i=1;i<=k;i++)//正好删除k个人
{
s=(s-1+m)%t;//走一步,取余
t--;//删去一人
if(s<k) return false;//删除好人,不合法
}
return true;
}
int main()
{
int i,j;
for(i=1;i<=13;i++)//把所有情况处理出来
{
j=i+1;
while(!fun(i,j))
j++;
a[i]=j;
}
int k;
while(cin>>k && k)//hh
cout<<a[k];
return 0
为什么要都一起打个表然后再输出呢?呵呵,就是告诉你们它有多快。
3.轰炸(LuoguP1142)
题目描述:
“我该怎么办?”飞行员klux向你求助。
事实上,klux面对的是一个很简单的问题,但是他实在太菜了。
klux要想轰炸某个区域内的一些地方,它们是位于平面上的一些点,但是(显然地)klux遇到了抵抗,所以klux只能飞一次,而且由于飞机比较破,一点起飞就只能沿直线飞行,无法转弯。现在他想一次轰炸最多的地方。
思路:
其实就是给出一个点集让你求同一条直线上最多有多少个点。其实在一顿狂导公式之后就已经非常的水了。还有不要觉得是O(n^3)就会T,自己看看时间。因为每次扫描一个点都只是O(n)的复杂度。
代码:
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<string>
#include<cstring>
#include<iostream>
using namespace std;
struct point
{
int x,y;
};
point a[705];
int n=1;
int ans=0;
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d%d",&a[i].x,&a[i].y);
for(int i=1;i<=n;i++)
for(int j=i+1;j<=n;j++)
{
int t1=a[i].x-a[j].x;
int t2=a[i].y-a[j].y;
int judge=a[j].x*a[i].y-a[i].x*a[j].y;
int po=0;
for(int k=1;k<=n;k++)
if(a[k].x*t2-a[k].y*t1==judge) po++;//不懂公式请自己导
ans=max(ans,po);
}
printf("%d\n",ans);
return 0;
}
4.点和线
拒绝写跨立实验这种恶心题解……