题意:求前五个完美数。
思路:完全数:又称完美数,完备数。所有除了自身以外的约数的和,恰好等于它本身。目前共发现48个完美数。(好像说完美数一定是以6或者8结尾。)
前9个完美数分别为:6、28、496、8128、33550336、8589869056、137438691328、2305843008139952128、2658455991569831744654692615953842176。
欧拉曾推出完美数的公式:如果p是质数,且2^p-1也是质数,那么(2^p-1)*2^(p-1)便是一个完全数。
利用上述性质即可打印出前几个完美数,然后大表即可。
打表代码:(至于为什么而打印出来的完美数一定是前几个......我也不知道)
#include<iostream>
#include<iomanip>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<string>
#include<queue>
#include<stack>
#include<vector>
#include<map>
#include<set>
#include<sstream>
#include<cstdlib>
#include<time.h>
#define rep(i,a,n) for(int i=a;i<=n;i++)
#define repp(i,n,a) for(int i=n;i>=a;i--)
#define ll long long
#define ull unsigned long long
#define mem(a,x) memset((a),(x),sizeof ((a)))//x只能是0或-1或false或true
#define debug(x) cout<<"X: "<<(x)<<endl
#define de cout<<"************"<<endl
#define lowbit(x) ((x)&(-x))
#define lson rt<<1
#define rson rt<<1|1
#define gcd(a,b) __gcd(a,b)
#define lcm(a,b) a*b/(__gcd(a,b))
#define inf 0x3f3f3f3f//1e9+6e7
#define Eps 1e-8
#define Mod 1e9+7
#define maxn 100010
const double pi=acos(-1.0);
using namespace std;
const int N=10000010;
bool prime[N];
void init()
{
mem(prime,true);
prime[0]=false;
prime[1]=false;
rep(i,1,N-1)
{
if(prime[i])
for(int j=2;i*j<N-1;j++)
prime[i*j]=false;
}
}
ll pow_mod(int a,int b)
{
ll ret=1;
while(b)
{
if(b&1)
ret*=a;
a=a*a;
b/=2;
}
return ret;
}
int main()
{
init();
rep(i,2,N-1)
{
if(prime[i]&&prime[pow_mod(2,i)-1])
cout<<(pow_mod(2,i)-1)*pow_mod(2,i-1)<<endl;
}
return 0;
}
#include<iostream>
#include<iomanip>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<string>
#include<queue>
#include<stack>
#include<vector>
#include<map>
#include<set>
#include<sstream>
#include<cstdlib>
#include<time.h>
#define rep(i,a,n) for(int i=a;i<=n;i++)
#define repp(i,n,a) for(int i=n;i>=a;i--)
#define ll long long
#define ull unsigned long long
#define mem(a,x) memset((a),(x),sizeof ((a)))//x只能是0或-1或false或true
#define debug(x) cout<<"X: "<<(x)<<endl
#define de cout<<"************"<<endl
#define lowbit(x) ((x)&(-x))
#define lson rt<<1
#define rson rt<<1|1
#define gcd(a,b) __gcd(a,b)
#define lcm(a,b) a*b/(__gcd(a,b))
#define inf 0x3f3f3f3f//1e9+6e7
#define Eps 1e-8
#define Mod 1e9+7
#define maxn 100010
const double pi=acos(-1.0);
using namespace std;
int main()
{
cout<<"6"<<endl;
cout<<"28"<<endl;
cout<<"496"<<endl;
cout<<"8128"<<endl;
cout<<"33550336"<<endl;
return 0;
}
题意:给一个主串S,询问n次,每次给出一个串Ti,问Ti是否为S的子序列。
用 nxt [i] [j] 记录位置 i 后 j 第一次出现的位置。查询直接往后跳即可。
#include<iostream>
#include<iomanip>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<string>
#include<queue>
#include<stack>
#include<vector>
#include<map>
#include<set>
#include<sstream>
#include<cstdlib>
#include<time.h>
#define rep(i,a,n) for(int i=a;i<=n;i++)
#define repp(i,n,a) for(int i=n;i>=a;i--)
#define ll long long
#define ull unsigned long long
#define mem(a,x) memset((a),(x),sizeof ((a)))//x只能是0或-1或false或true
#define debug(x) cout<<"X: "<<(x)<<endl
#define de cout<<"************"<<endl
#define lowbit(x) ((x)&(-x))
#define lson rt<<1
#define rson rt<<1|1
#define gcd(a,b) __gcd(a,b)
#define lcm(a,b) a*b/(__gcd(a,b))
#define inf 0x3f3f3f3f//1e9+6e7
#define Eps 1e-8
#define Mod 1e9+7
#define maxn 100010
const double pi=acos(-1.0);
using namespace std;
char s[100010];
char t[1010];
int nex[100010][30];
void getnext()
{
rep(i,0,100009)
rep(j,0,29)
nex[i][j]=-1;
int len=strlen(s+1);
repp(i,len,1)
{
int a=s[i]-'a'+1;
rep(j,1,26)
{
if(j==a)
nex[i-1][j]=i;
else
nex[i-1][j]=nex[i][j];
}
}
rep(i,1,26)
{
if(s[1]-'a'+1==i)
nex[0][i]=1;
else
nex[0][i]=nex[1][i];
}
}
int main()
{
scanf("%s",s+1);
getnext();
int n;
cin>>n;
while(n--)
{
scanf("%s",t+1);
int tlen=strlen(t+1);
int p=0;
int f=0;
rep(i,1,tlen)
{
p=nex[p][t[i]-'a'+1];
if(p==-1)
{f++;break;}
}
if(f==0)
cout<<"YES"<<endl;
else
cout<<"NO"<<endl;
}
return 0;
}
思维,推公式,左下角那个格有两种情况,右上角那个格有两种情况,左上角和右下角只有一种情况,其他的格有三种情况,所以答案就是 2*2*(3^(n-2))%mod ,快速幂一下就行了。当n等1的时候需要特判一下。
#include<iostream>
#include<iomanip>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<string>
#include<queue>
#include<stack>
#include<vector>
#include<map>
#include<set>
#include<sstream>
#include<cstdlib>
#include<time.h>
#define rep(i,a,n) for(int i=a;i<=n;i++)
#define repp(i,n,a) for(int i=n;i>=a;i--)
#define ll long long
#define ull unsigned long long
#define mem(a,x) memset((a),(x),sizeof ((a)))//x只能是0或-1或false或true
#define debug(x) cout<<"X: "<<(x)<<endl
#define de cout<<"************"<<endl
#define lowbit(x) ((x)&(-x))
#define lson rt<<1
#define rson rt<<1|1
#define gcd(a,b) __gcd(a,b)
#define lcm(a,b) a*b/(__gcd(a,b))
#define inf 0x3f3f3f3f//1e9+6e7
#define Eps 1e-8
#define Mod 1000000007
#define maxn 100010
const double pi=acos(-1.0);
using namespace std;
ll pow_mod(ll a,ll b,ll mod)
{
ll ret=1;
while(b)
{
if(b&1)
{ret=(ret*a)%mod;b--;}
a=(a*a)%mod;
b>>=1;
}
return ret;
}
int main()
{
ll n;
cin>>n;
if(n==1)
{cout<<"1";return 0;}
cout<<4*pow_mod(3,n-2,Mod)%Mod<<endl;
return 0;
}
通过打表能推出公式, r 和 l 的差值每个4个一循环。
这题用cout竟然会超时,改成printf就过了,真的是......以后干脆都不用cin cout了,都改成scanf printf算了......
打表代码:
#include<iostream>
#include<iomanip>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<string>
#include<queue>
#include<stack>
#include<vector>
#include<map>
#include<set>
#include<sstream>
#include<cstdlib>
#include<time.h>
#define rep(i,a,n) for(int i=a;i<=n;i++)
#define repp(i,n,a) for(int i=n;i>=a;i--)
#define ll long long
#define ull unsigned long long
#define mem(a,x) memset((a),(x),sizeof ((a)))//x只能是0或-1或false或true
#define debug(x) cout<<"X: "<<(x)<<endl
#define de cout<<"************"<<endl
#define lowbit(x) ((x)&(-x))
#define lson rt<<1
#define rson rt<<1|1
#define gcd(a,b) __gcd(a,b)
#define lcm(a,b) a*b/(__gcd(a,b))
#define inf 0x3f3f3f3f//1e9+6e7
#define Eps 1e-8
#define Mod 1e9+7
#define maxn 100010
const double pi=acos(-1.0);
using namespace std;
int a[1010];
int f[110][110],g[110][110],w[110][110];
void ff(int x,int y)
{
rep(i,x,y)
{a[i]++;}//a[j]++;}
}
void gg(int x,int y)
{
rep(i,x,y)
rep(j,i,y)
ff(i,j);
}
int main()
{
int n;
cin>>n;
rep(i,1,n)
a[i]=i;
int q;
cin>>q;
int l,r;
while(q--)
{
scanf("%d%d",&l,&r);
mem(a,0);
rep(i,l,r)
rep(j,i,r)
{
gg(i,j);
}
rep(i,l,r)
if(a[i]%2==1)
cout<<"##"<<i<<endl;
cout<<endl;
}
return 0;
}
/*
100
1000
1 1
1 2
1 3
1 4
1 5
1 6
1 7
1 8
1 9
1 10
1 11
1 12
1 13
1 14
1 15
1 16
1 17
1 18
1 19
1 20
2 2
2 3
2 4
2 5
2 6
2 7
2 8
2 9
2 10
2 11
2 12
2 13
2 14
2 15
2 16
2 17
2 18
2 19
2 20
*/
AC code:
#include<iostream>
#include<iomanip>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<string>
#include<queue>
#include<stack>
#include<vector>
#include<map>
#include<set>
#include<sstream>
#include<cstdlib>
#include<time.h>
#define rep(i,a,n) for(int i=a;i<=n;i++)
#define repp(i,n,a) for(int i=n;i>=a;i--)
#define ll long long
#define ull unsigned long long
#define mem(a,x) memset((a),(x),sizeof ((a)))//x只能是0或-1或false或true
#define debug(x) cout<<"X: "<<(x)<<endl
#define de cout<<"************"<<endl
#define lowbit(x) ((x)&(-x))
#define lson rt<<1
#define rson rt<<1|1
#define gcd(a,b) __gcd(a,b)
#define lcm(a,b) a*b/(__gcd(a,b))
#define inf 0x3f3f3f3f//1e9+6e7
#define Eps 1e-8
#define Mod 1e9+7
#define maxn 100010
const double pi=acos(-1.0);
using namespace std;
int a[100010];
int b[100010];
int main()
{
int T;
cin>>T;
while(T--)
{
mem(a,0);
mem(b,0);
int n;
scanf("%d",&n);
rep(i,1,n)
scanf("%d",&a[i]);
b[1]=a[1];
b[2]=a[2];
b[3]=a[3];
b[4]=a[4];
rep(i,5,n)
b[i]=b[i-4]^a[i];
int q,l,r;
scanf("%d",&q);
while(q--)
{
scanf("%d%d",&l,&r);
if((r-l+1)%4==0)
{
printf("0\n");
continue;
}
//{cout<<"0"<<endl;continue;}
if((r-l+1)%4==1)
{
if(l>4)
printf("%d\n",(b[l+(r-l)/4*4]^b[l-4]));
//cout<<(b[l+(r-l)/4*4]^b[l-4])<<endl;
else
printf("%d\n",b[l+(r-l)/4*4]);
//cout<<b[l+(r-l)/4*4]<<endl;
continue;
}
if((r-l+1)%4==2)
{
int ans=0;
if(l>4)
ans^=b[l+(r-l)/4*4]^b[l-4];
else
ans^=b[l+(r-l)/4*4];
l++;
if(l>4)
ans^=b[l+(r-l)/4*4]^b[l-4];
else
ans^=b[l+(r-l)/4*4];
printf("%d\n",ans);
//cout<<ans<<endl;
continue;
}
if((r-l+1)%4==3)
{
l++;
if(l>4)
printf("%d\n",(b[l+(r-l)/4*4]^b[l-4]));
//cout<<(b[l+(r-l)/4*4]^b[l-4])<<endl;
else
printf("%d\n",b[l+(r-l)/4*4]);
//cout<<b[l+(r-l)/4*4]<<endl;
continue;
}
}
}
return 0;
}
题意:求 “ 区间最小值 * 区间和 ” 的最大值。
思路:二分 + ST表求区间最值 + 线段树求区间最大子段和
用dp[i] 表示以 a [i] 为最小值的所有区间中答案最大的值,那么把dp数组求出来了,只需要枚举一遍找最大值就行了。
当 a[i] 为正数的时候,只需要让这个区间的区间和尽可能的大;当 a[i] 为负数的时候,只需要让这个区间的区间和尽可能的小;
求指定区间的最大子段和和最小子段和,我们可以用线段树来做。
那么怎样求以 a[i] 为最小值的最长区间呢(因为区间越长,那么区间的最大子段和才会越大,最小子段和才会越小)?我们可以二分,用ST表O(1)查询区间最值,然后进行二分。
下面的代码中二分写的有点乱,也是自己写了几组样例然后改来改去......
AC code:
#include<iostream>
#include<iomanip>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<string>
#include<queue>
#include<stack>
#include<vector>
#include<map>
#include<set>
#include<sstream>
#include<cstdlib>
#include<time.h>
#define rep(i,a,n) for(int i=a;i<=n;i++)
#define repp(i,n,a) for(int i=n;i>=a;i--)
#define ll long long
#define ull unsigned long long
#define mem(a,x) memset((a),(x),sizeof ((a)))//x只能是0或-1或false或true
#define debug(x) cout<<"X: "<<(x)<<endl
#define de cout<<"************"<<endl
#define lowbit(x) ((x)&(-x))
#define lson rt<<1
#define rson rt<<1|1
#define gcd(a,b) __gcd(a,b)
#define lcm(a,b) a*b/(__gcd(a,b))
#define inf 0x3f3f3f3f//1e9+6e7
#define Eps 1e-8
#define Mod 1e9+7
#define maxn 100010
const double pi=acos(-1.0);
using namespace std;
const int SIZE=500010;
#define l(x) tree[x].l
#define r(x) tree[x].r
#define sum(x) tree[x].sum
#define add(x) tree[x].add
struct node{
ll l,r;
ll sum,lmax,rmax,dat;
ll lmin,rmin,datt;
}t[SIZE*4];
ll a[SIZE],n,m;
ll ff[SIZE][20];
ll x;
void build(ll p,ll l,ll r)
{
t[p].l=l;
t[p].r=r;
if(l==r)
{
scanf("%lld",&x);
a[l]=x;
t[p].dat=t[p].lmax=t[p].rmax=t[p].sum=x;
t[p].datt=t[p].lmin=t[p].rmin=t[p].sum=x;
return ;
}
ll mid=(l+r)/2;
build(p*2,l,mid);
build(p*2+1,mid+1,r);
t[p].sum=t[p*2].sum+t[p*2+1].sum;
t[p].lmax=max(t[p*2].lmax,t[p*2].sum+t[p*2+1].lmax);
t[p].rmax=max(t[p*2+1].rmax,t[p*2+1].sum+t[p*2].rmax);
t[p].dat=max(max(t[p*2].dat,t[p*2+1].dat),t[p*2].rmax+t[p*2+1].lmax);
t[p].lmin=min(t[p*2].lmin,t[p*2].sum+t[p*2+1].lmin);
t[p].rmin=min(t[p*2+1].rmin,t[p*2+1].sum+t[p*2].rmin);
t[p].datt=min(min(t[p*2].datt,t[p*2+1].datt),t[p*2].rmin+t[p*2+1].lmin);
}
void change(ll p,ll x,ll y)
{
if(t[p].l==x&&t[p].r==x)
{
t[p].dat=t[p].lmax=t[p].rmax=t[p].sum=y;
return ;
}
ll mid=(t[p].l+t[p].r)/2;
if(mid<x) change(p*2+1,x,y);
else change(p*2,x,y);
t[p].sum=t[p*2].sum+t[p*2+1].sum;
t[p].lmax=max(t[p*2].lmax,t[p*2].sum+t[p*2+1].lmax);
t[p].rmax=max(t[p*2+1].rmax,t[p*2+1].sum+t[p*2].rmax);
t[p].dat=max(max(t[p*2].dat,t[p*2+1].dat),t[p*2].rmax+t[p*2+1].lmax);
}
node ask(ll p,ll l,ll r){//[l,r]询问的区间 ask(1,x,y)
if(t[p].l>=l&&t[p].r<=r){
return t[p];
}
ll mid=(t[p].l+t[p].r)>>1;
if(mid<l)return ask(p<<1|1,l,r);
else if(mid>=r)return ask(p<<1,l,r);
else
{
node a,b;
a=ask(p<<1,l,r);
b=ask(p<<1|1,l,r);
node tt;
tt.dat=max(max(a.dat,b.dat),a.rmax+b.lmax);
tt.lmax=max(a.lmax,a.sum+b.lmax);
tt.rmax=max(b.rmax,a.rmax+b.sum);
tt.datt=min(min(a.datt,b.datt),a.rmin+b.lmin);
tt.lmin=min(a.lmin,a.sum+b.lmin);
tt.rmin=min(b.rmin,a.rmin+b.sum);
tt.sum=a.sum+b.sum;
return tt;
}
}
void ST_prework() //ST表O(n* log n)预处理
{
for(ll i=1;i<=n;i++)
ff[i][0]=a[i];
ll t=log(n)/log(2)+1;
for(ll j=1;j<t;j++)
for(ll i=1;i<=n-(1<<j)+1;i++)
ff[i][j]=min(ff[i][j-1],ff[i+(1<<(j-1))][j-1]);
}
ll ST_query(ll l,ll r)
{
ll k=log(r-l+1)/log(2);
return min(ff[l][k],ff[r-(1<<k)+1][k]);
}
ll findp1(ll x)
{
if(x==1)
return 1;
ll l=1,r=max((ll)1,x-1);
while(l<=r)
{
ll mid=(l+r)>>1;
if(ST_query(mid,r)<a[x])
l=mid+1;
else
r=mid-1;
}
if(ST_query(r,x-1)>a[x])
return max(min(x,r),(ll)1);
if(ST_query(l,x-1)>a[x])
return max(min(x,l),(ll)1);
else
return max(min(x,l+1),(ll)1);
}
ll findp2(ll x)
{
if(x==n)
return n;
ll l=min(x+1,n),r=n;
while(l<=r)
{
ll mid=(l+r)>>1;
if(ST_query(l,mid)<a[x])
r=mid-1;
else
l=mid+1;
}
if(ST_query(l,x+1)>a[x])
return min(max(x,l),n);
if(ST_query(r,x+1)>a[x])
return min(max(x,r),n);
else
return min(max(x,r-1),n);
}
ll dp[500010];
int main()
{
cin>>n;
build(1,1,n);
ST_prework(); //ST表预处理
rep(i,1,n)
{
dp[i]=a[i]*a[i]; //对dp数组初始化
ll p1=1,p2=n;
p1=findp1(i); //寻找以a[i]为最小值的区间的左端点
p2=findp2(i); //寻找以a[i]为最小值的区间的右端点
node q1=ask(1,p1,i); //线段树计算a[p1]到a[i]中以a[i]为结尾的最大子段和和最小子段和 时间O(log n)
node q2=ask(1,i,p2); //线段树计算a[i]到a[p2]中以a[i]为起始的最大子段和和最小子段和 时间O(log n)
if(a[i]>0)
dp[i]=max(dp[i],(q1.rmax+q2.lmax-a[i])*a[i]);
if(a[i]<0)
dp[i]=max(dp[i],(q1.rmin+q2.lmin-a[i])*a[i]);
}
ll ans=-10;
rep(i,1,n)
{ans=max(ans,dp[i]);}
cout<<ans<<endl;
return 0;
}