1.积分之迷
小明开了个网上商店,卖风铃。共有3个品牌:A,B,C。你能算出第三笔订单需要返积分多少吗?
答案:105
2.
完美正方形
如果一些边长互不相同的正方形,可以恰好拼出一个更大的正方形,则称其为完美正方形。请提交紧贴着下边沿的正方形的边长,从左到右,用空格分开。
#include
using namespace std;
// 全局变量
namespace Global
{
const int MaxS = 46+47+61; // 正方形的边长
int All[] = {2,5,9,11,16,17,19,21,22,
24,26,30,31,33,35,36,41,50,52
};// 备选正方形边长
int Length = sizeof(All)/sizeof(All[0]);// 备选正方形的数量
int Square[MaxS][MaxS]= {0}; // 表示结果的完美正方形
}
// 线段树结点
struct TNode
{
int L, R; // [L, R]
int height; // 段高度( -1时表示该段不平滑,高度无意义 )
int inc; // 高度增量
// 计算宽度
inline int Width()const
{
return R-L+1;
}
// 计算中点
inline int Mid()const
{
return (L+R)>>1;
}
} NSet[1024];
inline int LSon( int i )
{
return i<<1;
}
inline int RSon( int i )
{
return LSon(i)+1;
}
inline int Parent( int i)
{
return i>>1;
}
// 建立线段树
void BuildTree( int i, int L, int R )
{
TNode* p = NSet+i;
p->L = L;
p->R = R;
p->height = 0;
p->inc = 0;
if( L < R )
{
int m = p->Mid();
BuildTree( LSon(i), L, m );
BuildTree( RSon(i), m+1, R);
}
}
// 增量的向下传递调整
// 注: NSet[i]必须为平滑区间
inline void Adjust( int i )
{
if( NSet[i].inc != 0 )
{
NSet[i].height += NSet[i].inc;
if( NSet[i].L != NSet[i].R )
{
NSet[LSon(i)].inc += NSet[i].inc;
NSet[RSon(i)].inc += NSet[i].inc;
}
NSet[i].inc = 0;
}
}
// 将区间[L,R]的高度统一增加(或减少)inc
// 注: 区间 [L, R] 必须平滑
void Add(int i, int L, int R, int inc )
{
TNode* p = NSet+i;
if( p->L == L && p->R == R )
{
// 操作后平滑性不变
p->inc += inc;
Adjust(i);
}
else
{
int m = p->Mid();
if( p->height != -1 ) // 表示该段本是平滑的
{
Adjust(i);
p->height = -1; // 现在开始该段不再平滑
}
int ls = LSon(i), rs = RSon(i);
if( R <= m )
Add( ls, L, R, inc );
else if( L > m )
Add( rs, L, R, inc );
else
{
Add( ls, L, m, inc );
Add( rs, m+1, R, inc );
}
// 平滑性恢复检验
if(NSet[ls].height != -1)
{
Adjust(ls);
if(NSet[rs].height != -1)
{
Adjust(rs);
if(NSet[ls].height == NSet[rs].height)
p->height = NSet[ls].height;
}
}
} // end else
}
// 获取最低段区间
void GetLowestInterval(int i, TNode* prev, TNode* lowest )
{
TNode* p = NSet+i;
if( p->height == -1 )
{
GetLowestInterval( LSon(i), prev, lowest );
GetLowestInterval( RSon(i), prev, lowest );
}
else
{
prev->R = p->R;
// 检验等高区间连续性
if( p->height != prev->height )
{
prev->L = p->L;
prev->height = p->height;
}
// 更新最低区间
if( prev->height <= lowest->height )
{
lowest->height = prev->height;
lowest->L = prev->L;
lowest->R = prev->R;
}
}
}
bool Dfs( int L, int R ,int H )
{
if( L > R )
{
TNode p, m;
m.height = 1000;
m.L = m.R = 1000;
p.height = 1000;
p.L = p.R = -1;
GetLowestInterval(1, &p, &m);
L = m.L;
R = m.R;
H = m.height;
}
int Width = R-L+1, temp=0;
if( Width == Global::MaxS && H != 0 ) return true;
for( int i = Global::Length; i-- > 0 ;)
{
temp = Global::All[i];
if( temp != 0 && temp <= Width )
{
Global::All[i] = 0;
Add( 1, L, L+temp-1, temp);
Global::Square[ H+temp-1 ][ L ] = temp;
if( Dfs( L+temp, R, H ) == true ) return true;
Add( 1, L, L+temp-1, -temp);
Global::All[i] = temp;
}
}
return false;
}
int main(int argc, char** argv)
{
BuildTree( 1, 0, Global::MaxS-1 );
Add( 1, 0, 46, 47);
Add( 1, 47, 92, 46);
Add( 1, 93, 153, 61);
if( Dfs( 1, 0, 0 ) )
{
for( int i = 0,t=0; i < Global::MaxS; i+=t)
{
t = Global::Square[ Global::MaxS-1 ][i];
cout << t << ' ';
}
}
return 0;
}
关联账户
为增大反腐力度,某地警方专门支队,对若干银行账户展开调查。小明给出了如下的解决方案:
#include
#define N 100
int connected(int* m, int p, int q)
{
return m[p]==m[q]? 1 : 0;
}
void link(int* m, int p, int q)
{
int i;
if(connected(m,p,q)) return;
int pID = m[p];
int qID = m[q];
for(i=0; i
答案: if( m[i] == qID) m[i]=pID ;
4.密文搜索
福尔摩斯从X星收到一份资料,全部是小写字母组成。提交时,注意选择所期望的编译器类型。
思路:因为要求每行密码的所有排列在s中匹配次数的总和,所以可以统计每行密码中所包含的各个字母的个数,然后选取主串中的长度为8的区间,比较是否与密码中包含的各个字母的个数相等。在选取主串中长度为8的区间时,实际上只有只有主串长度-7个长度为8的区间。
例如: 0 1 2 3 4 5 6 7 8 9 10 主串长度为11
则长度为8的区间只有0--7 1-- 8 2--9 3--10这4个,即11-4个。
#include
#include
#include
#include
#include
using namespace std;
int sum1[30],sum2[1000][30];
int sum=0, n;
int main (){
char ch1[1024*1024];
char ch2[10];
scanf("%s",ch1);
scanf("%d",&n);
memset(sum1,0,sizeof(sum1));
memset(sum2,0,sizeof(sum2));
for(int i=0;i<8;i++)
sum1[ ch1[i] -'a' ]++;
for(int i=0;i7){
sum1[ ch1[i-8]-'a' ]--;
sum1[ ch1[i]-'a' ]++;
}
for(int j=0;j
一个用素数解决的不错的方法
#include
#include
#include
#define maxn 1<<20+5
using namespace std;
char str[maxn],s[10];
int le[]={2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,101,103,107};
long mul[maxn];
int main(){
int k=0;
char c;
mul[0]=1;
while(scanf("%c",&c)!=EOF){
if(c=='\n') break;
str[k++]=c;
mul[k]=mul[k-1]*le[c-'a'];
}
int n;
int res=0;
scanf("%d",&n);
getchar();
for(int i=0;i
5.居民集会
蓝桥村的居民都生活在一条公路的边上,公路的长度为L,每户家庭的位置都用这户家庭到公路的起点的距离来计算,第i户家庭距起点的距离为di。提交时,注意选择所期望的编译器类型。
dp[i][j]=min(dp[i-1][j]+sum[i-1][j]*(A[i]-A[i-1]),dp[i-1][j-1]);
#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define INF 1.0e14;
const int maxn = 1e5+100;
typedef long long LL;
int A[maxn];
int B[maxn];
LL dp[maxn][4];
LL sum[maxn][4];
int main(){
int n,m;
scanf("%d%d",&n,&m);
int i,j,k;
for(i=1;i<=n;i++)
scanf("%d%d",&A[i],&B[i]);
for(i=1;i<=n;i++){
dp[i][0]=dp[i-1][0]+sum[i-1][0]*(A[i]-A[i-1]);
sum[i][0]=sum[i-1][0]+B[i];
for(j=1;j<=3;j++)
if(i==j){
dp[i][j]=dp[i-1][j-1];
sum[i][j]=B[i];
}
else if(i>j){
dp[i][j]=dp[i-1][j]+sum[i-1][j]*(A[i]-A[i-1]);
sum[i][j]=sum[i-1][j]+B[i];
if(dp[i][j]>=dp[i-1][j-1])
dp[i][j]=dp[i-1][j-1],sum[i][j]=B[i];
}
}
LL ans=dp[n][0];
if(n>1) ans=min(ans,dp[n][1]);
if(n>2) ans=min(ans,dp[n][2]);
if(n>3) ans=min(ans,dp[n][3]+sum[n][3]*(m-A[n]));
cout<
6.模型染色
在电影《超能陆战队》中,小宏可以使用他的微型机器人组合成各种各样的形状。提交时,注意选择所期望的编译器类型。