素数列表
小李是希望小学六年级的学生,在一次数学课上,张老师出了一道题,小李很快就答出来了。这个题目是这样的:给定一个正整数 N,请求出 2 ~ N之间长度最长的、成等差数列的素数(质数)。例如:当 N 的值为 40 时,在 2 ~ 40 之间的全部素数有: 2 , 3 , 5 , 7 , 11 , 13 , 17 , 19 ,23 , 29 , 31 , 37 。其中公差(每两个数之间的差)为 1的素数数列为 2,3 ,其长度(素数的个数)为 2 ; 公差为 2 的素数数列为 3,5,7 ,其长度为3 ; ⋯⋯
用素数筛把所有的素数筛出来,然后枚举公差,如果满足那么可以继续,否则记录答案
#include<bits/stdc++.h>
#define maxn 10010
using namespace std;
int vis[maxn],a[maxn],n,tep;
inline void su()
{
vis[1]=1;
for(int i=2;i<=n;i++)
{
if(!vis[i])
{
a[++tep]=i;
for(int j=i*2;j<=n;j+=i)vis[j]=1;
}
}
}
inline int read()
{
int f=1,res=0;
char ch=getchar();
while(!isdigit(ch))ch=getchar();
while(isdigit(ch))res=(res<<1)+(res<<3)+(ch&15),ch=getchar();
return res;
}
int ans,nans[maxn];
int main()
{
n=read();su();
// for(int i=1;i<=tep;i++)cout<<a[i]<<' ';
for(int i=1;i<=tep;i++)
{
for(int j=1;j<=n;j++)
{
int k=1,w=a[i];
while(!vis[w+j]&&w+j<=n)w+=j,k++;
if(k>ans)
{
ans=k;
for(int p=0;p<k;p++)
nans[p+1]=a[i]+j*p;
}
}
}
cout<<ans<<endl;
for(int i=1;i<=ans;i++)cout<<nans[i]<<' ';
return 0;
}
铺地砖
*轻而一举地就可以猜到递推式,dp[n]=dp[n-1]+dp[n-2]2,然后发现数据太大,那么多开一位写高精
#include<bits/stdc++.h>
using namespace std;
int n;
inline int read()
{
int f=1,res=0;
char ch=getchar();
while(!isdigit(ch))ch=getchar();
while(isdigit(ch))res=(res<<1)+(res<<3)+(ch&15),ch=getchar();
return res;
}
int dp[150][1000];
inline void gj(int i,int j,int k)//高精
{
int jw=0;int t=0;
for(int ii=0;ii<=1000;ii++)
{
dp[i][ii]=(dp[j][ii]+dp[k][ii]*2+jw)%10;
jw=(dp[j][ii]+dp[k][ii]*2+jw)/10;
}
}
int main()
{
n=read();
dp[1][0]=1;dp[2][0]=3;
for(int i=3;i<=n;i++)gj(i,i-1,i-2);//地推
int k=800;
while(!dp[n][k])k--;
// cout<<k<<' ';
for(int i=k;i>=0;i--)cout<<dp[n][i];
return 0;
}
扫雷
简简单单的dfs(大法师)+剪枝
#include<bits/stdc++.h>
using namespace std;
int n;
inline int read()
{
int f=1,res=0;
char ch=getchar();
while(!isdigit(ch))ch=getchar();
while(isdigit(ch))res=(res<<1)+(res<<3)+(ch&15),ch=getchar();
return res;
}
int l[45],vis[45],ans,nans,r[45];
inline bool check()
{
for(int i=1;i<=n;i++)//是不是扫完了
if(l[i])return 0;
return 1;
}
inline void dfs(int x,int last)
{
if(check())
{
for(int i=1;i<=n;i++)cout<<vis[i];
cout<<endl<<x;
exit(0);
}
for(int i=last+1;i<=n;i++)
{
if(!vis[i])
{
if(l[i-1]>=1&&l[i+1]>=1&&l[i]>=1)//满足还可以放下去,剪枝
{
l[i]--;
l[i+1]--;
l[i-1]--;
vis[i]=1;
dfs(x+1,i);
vis[i]=0;//还原现场
l[i]++;
l[i+1]++;
l[i-1]++;
}
}
}
}
int main()
{
n=read();
l[0]=l[n+1]=0x7fffffff;
for(int i=1;i<=n;i++)l[i]=read(),r[i]=l[i];
dfs(0,0);
return 0;
}
写作文
先是用二维矩阵前缀和,算出从1,1开始到i,jblack的数目和white的数目
然后枚举边长和起点,算出black与white的差值,如果<=1,那么可以记录答案
#include<bits/stdc++.h>
using namespace std;
int ww,bb,n,m,ans;
int x,w[350][350],b[350][350];
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
cin>>x;
if(!x)w[i][j]=w[i-1][j]+w[i][j-1]-w[i-1][j-1]+1,b[i][j]=b[i-1][j]+b[i][j-1]-b[i-1][j-1];//black
else b[i][j]=b[i-1][j]+b[i][j-1]-b[i-1][j-1]+1,w[i][j]=w[i-1][j]+w[i][j-1]-w[i-1][j-1];//white
}
for(int k=2;k<=min(n,m);k++)
for(int i=k;i<=n;i++)
for(int j=k;j<=m;j++)
{
ww=w[i][j]-w[i-k][j]-w[i][j-k]+w[i-k][j-k];
bb=b[i][j]-b[i-k][j]-b[i][j-k]+b[i-k][j-k];
if(abs(ww-bb)<=1)ans++;//差值小于等于一
}
cout<<ans;
return 0;
}