19116 丑数
时间限制:1000MS 代码长度限制:10KB
提交次数:0 通过次数:0
题型: 编程题 语言: G++;GCC
Description
“丑数”是指除了质因子2,3,5,不含其它质因子的正整数,例如由小到大前10个“丑数”为
1, 2, 3, 4, 5, 6, 8, 9, 10, 12, ...
现要求编写一个程序,输出指定第几位的“丑数”。
输入格式
第一行为正整数T(T<=10000), 表示case的数目。
此后T行,每行一个正整数 n (n <= 100000000).
输出格式
每一个n,输出第n个“丑数”
输入样例
3
1
2
9
输出样例
1
2
10
#include <iostream>
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
using namespace std;
void Uglynumber(int n)
{
int dp[n+5],i=1;
int a=1,b=1,c=1;
dp[1]=1;
for(i=2;i<=n;i++)
{
int at=dp[a]*2,bt=dp[b]*3,ct=dp[c]*5;
dp[i]=min(min(at,bt),ct);
if(dp[i]==at) a++;
if(dp[i]==bt) b++;
if(dp[i]==ct) c++;
}
cout<<dp[n]<<endl;
}
int main()
{
int T,n;
cin>>T;
while(T--)
{
cin>>n;
Uglynumber(n);
}
return 0;
}
18005 它不是丑数
“丑数”是指除了质因子2,3,5,不含其它质因子的正整数,例如由小到大前10个“丑数”为
1, 2, 3, 4, 5, 6, 8, 9, 10, 12, ...
非“丑数”的前10个数为
7, 11, 13, 14, 17, 19, 21, 22, 23, 26, ...
现要求编写一个程序,输出指定第几位的非“丑数”。
输入格式
第一行为正整数T(T<=10000), 表示case的数目。
此后T行,每行一个正整数 n (n <= 100000000).输出格式
每一个n,输出第n个非“丑数”
描述:先求出丑数数组,非丑数就是在两个丑数之间,因此用count计算两个丑数之间非丑数的数量并进行累加,直到大于m,然后再减去上一次非丑数的数量,再u[i]+m-count。
#include<iostream>
#include<cmath>
#include<algorithm>
#include<math.h>
using namespace std;
long long dp[100000]={1};
void ugly()
{
int i=1;
int a=1,b=1,c=1;
for(i<1200)
{
int at=2*dp[a],bt=3*dp[b],ct=5*dp[c];
dp[i]=min(min(at,bt),ct);
if(at==dp[i]) a++;
if(bt==dp[i]) b++;
if(ct==dp[i]) c++;
}
}
int main()
{
int m,n;
cin>>m;
ugly();
while(m--)
{
cin>>n;
int i=0,count=0;
while(count<n)
{
count+=dp[i+1]-dp[i]-1;
i++;
}
i--;
count-=dp[i+1]-dp[i]-1;
cout<<dp[i]+m-count<<endl;
i=0;
}
return 0;
}
18440 走迷宫
有一个N*M(N,M<=10)的格子迷宫,1代表该格子为墙,不能通过,0代表可以通过,人在迷宫中可以尝试上下
左右四个方向移动。另外,在迷宫中如果从左边走出迷宫会回到迷宫最右边一格(只要该格不是墙),行不变,
同样,从右边走出迷宫会回到迷宫最左边一格,向上走出迷宫会回到迷宫最下边一格,向下走出迷宫会回到迷宫
最上边一格。现在给定一个迷宫,以及起点和终点,问最少多少步可以走出迷宫。如果不能走出迷宫输出“die”。
输入格式
该程序为多CASE,第1行为CASE的数量
每一个CASE,第1行为两个数N(行)和M(列)
然后N行每行M个数,之后是起点坐标和终点坐标sc(行) sr(列) ec(行) er(列)
输出格式
如题
输入样例
2
4 3
011
010
110
110
0 0 3 2
2 2
01
10
0 0 1 1
输出样例
4
die
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <cstring>
using namespace std;
int n,m;
char map[11][11];
int dp[11][11];
int pocess(int x,int y,int sc,int sr)
{
if(x==-1)
x=m-1;
else if(x==m)
x=0;
if(y==-1)
y=n-1;
else if(y==n)
y=0;
if(map[y][x]=='1')
return 10000;
if(x==sc&&y==sr)
return 0;
map[y][x]='1';
if(dp[y][x]!=-1)
return dp[y][x];
dp[y][x]=min(min(pocess(x-1,y,sc,sr),pocess(x+1,y,sc,sr))
,min(pocess(x,y-1,sc,sr),pocess(x,y+1,sc,sr)))+1;
return dp[y][x];
}
int main()
{
int t;//case数量
cin>>t;
while(t--)
{
cin>>n>>m;//n行m列
memset(map,'1',sizeof(map));
memset(dp,-1,sizeof(dp));
int sc,sr,ec,er;
for(int i=0;i<n;i++)
{
string t;
cin>>t;
strcpy(map[i],t.c_str());
}
cin>>sr>>sc>>er>>ec;
pocess(ec,er,sc,sr);
if(dp[er][ec]!=10001)
cout<<dp[er][ec]<<endl;
else
cout<<"die"<<endl;
}
return 0;
}
// 注释版
#include <iostream>
#include <cstring>
#include <string>
using namespace std;
int n, m;
char map[11][11]; // 迷宫地图
int dp[11][11]; // 用于记忆化搜索的数组
// 递归函数,计算从当前位置 (x, y) 到起点 (sc, sr) 的最短路径长度
int process(int x, int y, int sc, int sr) {
// 处理边界情况,如果 x 或 y 超出迷宫边界,就将其转换为迷宫的另一侧
if (x == -1)
x = m - 1;
else if (x == m)
x = 0;
if (y == -1)
y = n - 1;
else if (y == n)
y = 0;
// 如果当前位置是墙壁,则返回一个很大的数表示不可达
if (map[y][x] == '1')
return 10000;
// 如果当前位置是起点,则返回路径长度为 0
if (x == sc && y == sr)
return 0;
// 标记当前位置为已访问
map[y][x] = '1';
// 如果该位置已经计算过最短路径,则直接返回存储的结果
if (dp[y][x] != -1)
return dp[y][x];
// 递归计算四个方向的最短路径长度,并加上当前步数
dp[y][x] = min(min(process(x + 1, y, sc, sr), process(x - 1, y, sc, sr)),
min(process(x, y + 1, sc, sr), process(x, y - 1, sc, sr)))
+ 1;
return dp[y][x];
}
int main() {
int t;
cin >> t; // 输入测试用例数量
while (t--) {
cin >> n >> m; // 输入迷宫的行数和列数
memset(map, '1', sizeof(map)); // 初始化迷宫地图,将所有位置设为墙壁
memset(dp, -1, sizeof(dp)); // 初始化记忆化搜索数组,-1 表示尚未计算
// 输入迷宫地图的每一行
for (int i = 0; i < n; i++) {
string t;
cin >> t;
strcpy(map[i], t.c_str()); // 将输入的字符串复制到迷宫地图的相应行中
}
int sr, sc, er, ec;
cin >> sr >> sc >> er >> ec; // 输入起点和终点的坐标
// 计算从起点 (sc, sr) 到终点 (ec, er) 的最短路径长度
process(ec, er, sc, sr);
// 输出计算结果,如果无法到达终点,则输出 "die"
if (dp[er][ec] != 10001)
cout << dp[er][ec] << endl;
else
cout << "die" << endl;
}
return 0;
}
18276 走迷宫2
时间限制:1000MS 代码长度限制:10KB
提交次数:0 通过次数:0
题型: 编程题 语言: G++;GCC;VC
Description
有一个N*M的格子迷宫,1代表该格子为墙,不能通过,0代表可以通过,另外,在迷宫中
有一些传送门,走到传送门的入口即会自动被传送到传送门的出口(一次传送算1步)。人在迷宫中可以尝试
上下左右四个方向移动。现在给定一个迷宫和所有传送门的出入口,以及起点和终点,
问最少多少步可以走出迷宫。如果不能走出迷宫输出“die”。
输入格式
该程序为多CASE,第1行为CASE的数量
每一个CASE,第1行为两个数N(行)和M(列)
然后N行每行M个数
之后是一个数W,为传送门的数量
之后每行一个传送门的入口坐标c1(行),r1(列)和出口坐标c2,r2
之后是起点坐标和终点坐标sc(行) sr(列) ec(行) er(列)
注:传送门出入口和起点坐标和终点坐标不会出现在墙的位置
所有数字不超过100
输出格式
如题
输入样例
2
4 3
011
011
110
110
1
1 0 2 2
0 0 3 2
2 2
01
10
0
0 0 1 1
输出样例
3
die
#include<iostream>
#include<queue>
#include<algorithm>
#include<cstring>
#define x first
#define y second
using namespace std;
typedef pair<int,int>PII;
const int N=110;
int n,m,w,c1,r1,c2,r2,sc,sr,ec,er;
char map[N][N];
int dp[N][N];
PII door[N][N];
void bfs()
{
memset(dp,-1,sizeof(dp));
dp[sc][sr]=0;
queue<PII>q;
q.push({sc,sr});
while(!q.empty())
{
PII t=q.front();
q.pop();
if(door[t.x][t.y].x!=-1&&door[t.x][t.y].y!=-1)
{
dp[door[t.x][t.y].x][door[t.x][t.y].y]=dp[t.x][t.y]+1;
q.push({door[t.x][t.y].x,door[t.x][t.y].y});
continue;
}
int dir[4][2]={0,1,0,-1,1,0,-1,0};
for(int i=0;i<4;i++)
{
int x=t.x+dir[i][0],y=t.y+dir[i][1];
if(x>=0&&x<n&&y>=0&&y<n&&map[x][y]!='1'&&dp[x][y]==-1)
{
dp[x][y]=dp[t.x][t.y]+1;
q.push({x,y});
}
}
}
}
int main()
{
int T;
cin>>T;
while(T--)
{
cin>>n>>m;
for(int i=0;i<n;i++)
{
for(int j=0;j<m;j++)
{
door[i][j].x=door[i][j].y=-1;
}
}
for(int i=0;i<n;i++)
{
string t;
cin>>t;
strcpy(map[i],t.c_str());
}
cin>>w;
for(int i=0;i<w;i++)
{
cin>>c1>>r1>>c2>>r2;
door[c1][r1].x=c2;
door[c1][r1].y=r2;
}
cin>>sc>>sr>>ec>>er;
bfs();
if(dp[ec][er]==-1)
cout<<"die"<<endl;
else
cout<<dp[ec][er]<<endl;
}
return 0;
}
18105 银行的叫号顺序
时间限制:8000MS 代码长度限制:10KB
提交次数:0 通过次数:0
题型: 编程题 语言: G++;GCC;VC
Description
银行的叫号过程是一个优先队列的典型应用,假设,银行有4类客户,分别用优先级1,2,3,4表示,级别越高
则更优先得到服务,例如,当前有三个人排队,两个1级客户,一个3级客户,则银行叫号时,3级客户将先得到服务
,即使另两个1级有客户比他先到。当多个同级的客户将获得服务时,由先到的客户先得到服务。
假设,银行只有一个服务窗口,一次只能服务一个客户,假设该窗口每5分钟服务一个客户,即叫号的时刻分别
为0分钟、5分钟、10分钟、.....如果在叫号的时侯,没有客户,银行职员会去喝杯咖啡或上个洗手间,5分钟后
再继续叫号。
银行给出一系列客户到来的记录,每条记录包括“客户到来的时”,“客户等级”,“客户姓名”(由一个单词构成),请输
出银行服务的客户的顺序。
输入格式
第一数字是客户的数量n(n<=100000)
此后,每一行是一个客户来访信息,包括3个数字,到来的时刻(分钟整点,最大10的8次方)、等级、姓名(最多20个字母)
(已经按到来时刻排序)
输出格式
按服务的先后顺序输出客户的姓名
输入样例
4
0 1 John
3 1 Smith
3 1 Tom
4 2 Flod
输出样例
John
Flod
Smith
Tom
#include<iostream>
#include<queue>
#include<utility>
#include<cstring>
using namespace std;
priority_queue<pair<int,string>>q;
int main()
{
int n;
int chazhi=99999;
int grade,time,realtime=0;
string name;
cin>>n;
while(n--)
{
cin>>time>>grade>>name;
cur:
if(time<=realtime)
{
q.push(make_pair(grade*100000+chazhi,name));
--chazhi;
continue;
}
if(!q.empty())
{
cout<<q.top().second<<endl;
q.pop();
}
realtime+=5;
goto cur;
}
while(!q.empty())
{
cout<<q.top().second<<endl;
q.pop();
}
return 0;
}
18216 银行服务
该题有题解
时间限制:8000MS 代码长度限制:10KB
提交次数:100 通过次数:8
题型: 编程题 语言: G++;GCC;VC
Description
银行通过叫号来决定服务用户的顺序,假设,银行有4类客户,分别用优先级1,2,3,4表示,级别越高
则更优先得到服务,例如,当前有三个人排队,两个1级客户,一个3级客户,则银行叫号时,3级客户将先得到服务
,即使另两个1级的客户比他先到。当多个同级的客户将获得服务时,由先到的客户先得到服务。
假设,银行只有一个服务窗口,一次只能服务一个客户,假设该窗口每5分钟服务一个客户,即叫号的时刻分别
为0分钟、5分钟、10分钟、.....如果在叫号的时侯,没有客户,银行职员会去喝杯咖啡或上个洗手间,5分钟后
再继续叫号。
有一种情况,银行工作到一定时间是要下班的,所以到一定时间,如果后面还有客户,将不再提供服务。
银行给出一系列客户到来的记录,每条记录包括“客户到来的时间”,“客户等级”,“客户姓名”(由一个单词构成),请输
出该银行这一轮服务的客户的顺序。
输入格式
第一行两个数字,第一数字是客户的数量n(n<=100000),第二个数字是银行关门的时间,到这个时间,即关门,该点及之后,
不再叫号,但之前已经叫号的客户会继续服务到完结。
此后,每一行是一个客户来访信息,包括3个数字,到来的时刻(分钟整点,最大10的8次方)、等级、姓名(最多20个字母)
(已经按到来时刻排序,注意:同一时刻可能会同时到来多个客户,这时若为同等级的,数据出现得早的稍早得到服务)
输出格式
按服务的先后顺序输出客户的姓名
输入样例
4 12
0 1 John
3 1 Smith
3 1 Tom
4 2 Flod
输出样例
John
Flod
Smith
#include<iostream>
#include<queue>
#include<utility>
#include<string.h>
#include<algorithm>
using namespace std;
priority_queue<pair<int ,string>>Q;
int main()
{
int n,t0,t,grade;
string name;
int now=0,index=99999;
cin>>n>>t0;
while(n--)
{
cin>>t>>grade>>name;
here:
if(t<=now)
{
Q.push(make_pair(grade*100000+index,name));
index--;
continue;
}
if(!Q.empty())
{
cout<<Q.top().second<<endl;
Q.pop();
}
now+=5;
goto here;
}
while(!Q.empty())
{
if(now>=t0)
break;
cout<<Q.top().second<<endl;
Q.pop();
now+=5;
}
return 0;
}
19121 小明手上的牌
时间限制:1000MS 代码长度限制:10KB
提交次数:0 通过次数:0
题型: 编程题 语言: G++;GCC
Description
有N张牌,编号由1到N,牌已经随机打乱。
(1)小明先从N张牌中取M张
(2)之后,将手中最小编号的牌丢弃,从没有抽取的牌中抽取一张补充到手牌中
(3)重复第(2)步,直到将N张牌全部取完,手中有M张牌。
问最后,小明手中最小编号的牌是什么?
输入格式
第一行两个正整数N和M(M<N<=100000)
此后N个数,为小明先后抽取的牌的编号。
输出格式
输出最后,小明手中最小编号的牌
输入样例
5 3
1 5 2 3 4
输出样例
3
#include<iostream>
#include<vector>
#include<queue>
#include<algorithm>
using namespace std;
typedef long long i64;
priority_queue<int,vector<int>,greater<int>>Q;
int main()
{
int n,m;
cin>>n>>m;
int a[m],b[n-m];
for(int i=0;i<m;i++)
{
cin>>a[i];
Q.push(a[i]);
}
for(int j=0;j<n-m;j++)
{
Q.pop();
cin>>b[i];
Q.push(b[i]);
}
cout<<Q.top()<<endl;
return 0;
}
19159 小明手上的牌2
#include<iostream
#include<queue>
#include<vector>
#include<algorithm>
using namespace std;
typedef long long i64;
priority_queue<int,vector<int>,greater<int>>Q;
int main()
{
int n,m;
cin>>n>>m;
int a[m],b[n-m];
for(int i=0;i<m;i++)
{
cin>>a[i];
Q.push(a[i]);
}
for(int j=0;j<n-m;j++)
{
cin>>b[j];
}
sort(b,b+n-m);
for(int j=0;j<n-m;j++)
{
Q.pop();
Q.push(b[j]);
}
cout<<Q.top()<<endl;
return 0;
}
18118 勇者斗恶龙
时间限制:800MS 代码长度限制:10KB
提交次数:0 通过次数:0
题型: 编程题 语言: G++;GCC;VC
Description
有n个头的恶龙,你希望雇一些骑士把它杀死(即砍掉所有头)。村里有m个骑士可以雇佣,一个能力值为x的骑士可以砍掉恶龙
一个直径不超过x的头,且需要支付x个金币。如何雇佣骑士才能砍掉恶龙的所有头,且需要支付的金币最少?注意,一个骑士只
能砍一个头(且不能被雇佣两次)
输入格式
多组数据,每组数据的第一行为正整数n和m(1<=n,m<=200000);以下n行每行为一个整数,即恶龙每个头的直径;以下m行每行为
一个整数,即每个骑士的能力。输入结束标志n=m=0;
输出格式
输出格式:每组数据,输出最少花费,无解输出"Loowater is doomed!"
输入样例
2 3
5
4
7
8
4
2 1
5
5
10
0 0
输出样例
11
Loowater is doomed!
#include<iostream>
#include<queue>
#include<functional>
using namespace std;
int main()
{
while(1)
{
priority_queue<int,vector<int>,greater<int>>dragon,worrior;
int n,m;
cin>>n>>m;
if(n==0&&m==0)
return 0;
int temp=0,cnt=0;
while(n--)
{
cin>>temp;
dragon.push(temp);
}
while(m--)
{
cin>>temp;
worrior.push(temp);
}
while(!dragon.empty()&&!worrior.empty())
{
if(dragon.top()<=worrior.top())
{
cnt=cnt+worrior.top();
dragon.pop();
worrior.pop();
}
else
{
worrior.pop();
}
}
if(dragon.empty())
{
cout<<cnt<<endl;
}
else
{
cout<<"Loowater is doomed!"<<endl;
}
}
return 0;
}
校赛排名
题型: 编程题 语言: G++;GCC;VC
Description
校赛结束了,每一个参赛选手由3个数据项构成(通过题数,用时分钟数,姓名),排名按照通过题数排序
通过题数多的排前,同题数的,罚时少的排前。如果题数相同,罚时也相同,而按数据读取的先后排。
给你N个参赛选手的数据,按排序先后,输出姓名
输入格式
第一个数为N,(N<=500000)
此后,每行一个参赛选手的数据,通过题数,用时分钟数,姓名,前两者为整型数,姓名为字符串(不多于20个字符)
输出格式
姓名排名
输入样例
4
3 5 Jon
5 100 Smith
3 5 Tom
6 95 Hel
输出样例
Hel
Smith
Jon
Tom
#include <iostream>
#include <queue>
#include <algorithm>
#include <stdio.h>
using namespace std;
struct Student
{
int cnt;
long long time;
char name[21];
};
bool cmp(Student a,Student b)
{
if(a.cnt!=b.cnt)
return a.cnt>b.cnt;
else if(a.time!=b.time)
return a.time<b.time;
else
return false;
}
Student student[500000];
int main()
{
int n;
scanf("%d",&n);
for(int i=0;i<n;i++)
{
scanf("%d %d %s",&student[i].cnt,&student[i].time,&student[i].name);
}
stable_sort(student,student+n,cmp);
for(int i=0;i<n;i++)
{
printf("%s\n",student[i].name);
}
return 0;
}
1142 巡逻的士兵
该题有题解
时间限制:1000MS 代码长度限制:10KB
提交次数:217 通过次数:58
题型: 编程题 语言: G++;GCC
Description
有N个士兵站成一队列, 现在需要选择几个士兵派去侦察。
为了选择合适的士兵, 多次进行如下操作: 如果队列超过三个士兵, 那么去除掉所有站立位置为奇数的士兵,
或者是去除掉所有站立位置为偶数的士兵。直到不超过三个战士,他们将被送去侦察。现要求统计按这样的方法,
总共可能有多少种不同的正好三个士兵去侦察的士兵组合方案。
注: 按上法得到少于三士兵的情况不统计。
1 <= N <= 2的32次方-1
输入格式
有多行(可能有上百行,尽量优化代码),每行一个数字N,最后一行是0
输出格式
对每一行的数字N,输出针对N的方案数
直到没有数字
输入样例
10
4
0
输出样例
2
0
#include<iostream>
#include<string.h>
#include<algorithm>
#include<queue>
using namespace std;
int F(int n)
{
if(n==3) return 1;
if(n<3) return 0;
if(n%2==0) return 2*F(n/2);
else return F(n/2)+F((n+1)/2);
}
int main()
{
int n;
while(cin>>n&&n)
{
cout<<F(n)<<endl;
}
return 0;
}
#include<iostream>
#include<string.h>
#include<queue>
#include<algorithm>
using namespace std;
int F(int n)
{
if(n==3) return 1;
else if(n<3) return 0;
else if(n%2==0) return 2*F(n/2);
else return F(n/2)+F((n+1)/2);
}
int main()
{
int n;
while(cin>>n&&n)
{
cout<<F(n)<<endl;
}
return 0;
}
18441 偷懒的士兵
时间限制:1000MS 代码长度限制:10KB
提交次数:0 通过次数:0
题型: 编程题 语言: G++;GCC;VC
Description
有N个士兵站成一队列, 现在需要选择几个士兵派去侦察。
为了选择合适的士兵, 多次进行如下操作: 如果队列超过三个士兵, 那么去除掉所有站立位置为奇数的士兵,
或者是去除掉所有站立位置为偶数的士兵。直到不超过三个战士,他们将被送去侦察。现有一个“聪明”的士兵,
经常通过选择站在合适的初始位置,成功避免被选中去侦察。这引起了陈教官的注意。陈教官希望你编写一个程序,
当给定士兵数之后,输出有多少个位置上的士兵是不可能被选中去巡逻的。
注: 按上法得到少于三士兵的情况不用去巡逻。
1 <= N <= 21亿
输入格式
有多行(可能有上百行,请尽量优化代码),每行一个数字N,最后一行是0
输出格式
对每一行的数字N,不可能被选中去巡逻的位置数
直到没有数字
输入样例
10
6
0
输出样例
4
0
#include <iostream>
using namespace std;
int F(int n)
{
if(n==3) return 1;
if(n<3) return 0;
if(n%2==0) return 2*F(n/2);
else return F(n/2)+F((n+1)/2);
}
int main()
{
int n;
while(cin>>n&&n)
{
cout<<n-3*F(n)<<endl;
}
return 0;
}
18442 偷懒的士兵2
时间限制:1000MS 代码长度限制:10KB
提交次数:0 通过次数:0
题型: 编程题 语言: G++;GCC;VC
Description
有N个士兵站成一队列, 现在需要选择几个士兵派去侦察。
为了选择合适的士兵, 多次进行如下操作: 如果队列超过三个士兵, 那么去除掉所有站立位置为奇数的士兵,
或者是去除掉所有站立位置为偶数的士兵。直到不超过三个战士,他们将被送去侦察。现有一个“聪明”的士兵,
经常通过选择站在合适的初始位置,成功避免被选中去侦察。这引起了陈教官的注意。陈教官希望你编写一个程序,
当给定士兵数之后,输出不可能被选中去巡逻的最少编号位置(如果不存在不可能被选中的位置,则输出0)。
注: 按上法得到少于三士兵的情况不用去巡逻。
1 <= N <= 100000
输入格式
有多行(不多于20行),每行一个数字N,最后一行是0
输出格式
对每一行的数字N,不可能被选中去巡逻的最小位置
直到没有数字
输入样例
9
6
0
#include<iostream>
#include<algorithm>
using namespace std;
int F(int n,int begin,int distance)
{
if(n==3) return 0;
if(n<3) return begin;
else
{
int a=F((n+1)/2,begin,distance*2);
int b=F(n/2,begin+distance,distance*2);
if(a&&b)
return min(a,b);
else if(a)
return a;
else if(b)
return b;
}
}
int main()
{
int n;
while(cin>>n&&n)
cout<<F(n,1,1)<<endl;
return 0;
}
#include<iostream>
#include<algorithm>
using namespace std;
int F(int n,int begin,int distance)
{
if(n==3) return 0;
else if(n<3) return begin;
else
{
int a=F((n+1)/2,begin,distance*2);
int b=F(n/2,begin+distance,distance*2);
if(a&&b)
{
return min(a,b);
}
else if(a)
return a;
else if(b)
return b;
}
}
int main()
{
int n;
while(cin>>n&&n)
{
cout<<F(n,1,1)<<endl;
}
return 0;
}
输出样例
2
0
18443 除法等式
时间限制:2000MS 代码长度限制:10KB
提交次数:0 通过次数:0
题型: 编程题 语言: G++;GCC;VC
Description
输入正整数n,按从小到大的顺序输出所有形如abcde/fghij=n的表达式,其中a~j各代表0~9中的一个数字
除了0可以重复外,其它数字不能重复,2<=n<=90000。
输入格式
多case,每行一个数字,最后一个数字是0
输出格式
除了最后一行0不用处理,
其它每个case,按被除数由小到大输出所有满足等式的情况
注:如果没有满足条件的等式,该case结束后,也需要输出一个空行
两个case之间用一个空行分隔
#include <iostream>
using namespace std;
int mark(int a,int b)
{
int book[10]= {0};
while(a)
{
book[a%10]++;
a/=10;
}
while(b)
{
book[b%10]++;
b/=10;
}
for(int i=1; i<10; i++)
{
if(book[i]>1) return 0;
}
return 1;
}
int main()
{
int T;
while(cin>>T&&T!=0)
{
for(int i=1; i<=50000; i++)
{
if(i*T>0&&i*T<=98765)
{
if(mark(i*T,i)==1)
{
printf("%05d/%05d=%d\n",i*T,i,T);
}
}
}
cout<<endl;
}
return 0;
}
#include<iostream>
#include<stdio.h>
using namespace std;
int mark(int a,int b)
{
int book[10]={0};
while(a)
{
book[a%10]++;
a/=10;
}
while(b)
{
book[b%10]++;
b/=10;
}
for(int i=1;i<10;i++)
{
if(book[i]>1) return 0;
}
return 1;
}
int main()
{
int T;
while(cin>>T&&T)
{
for(int i=1;i<=50000;i++)
{
if(i*T>0&&i*T<=98765)
{
if(mark(i*T,i)==1)
{
printf("%05d/%05d=%d\n",i*T,i,T);
}
}
}
cout<<endl;
}
}
1079 三角形
时间限制:500MS 代码长度限制:10KB
提交次数:283 通过次数:82
题型: 编程题 语言: G++;GCC
Description
著名的数学家毕达哥拉斯可能从来都不曾想过有人居然会问他这样的一个问题:给出一个整数,存在多少个直角三角形,
它的某一条边的长度等于这个整数,而且其他边的长度也是整数。既然毕达哥拉斯不可能预见到有计算机的出现,
如果他回答不出来,那谁又能责怪他呢?但是现在既然你有了计算机,那么回答不出来就说不过去了。
输入格式 第一行有一个整数n,代表有多少个数据(1<=n<=20)。接下来有n行,每行代表一个数据。一个数据就是一个整数ai(a<=i<=n,1<=ai<=100)。
输出格式
每个数据都必须有相应的输出。两个数据的输出之间有一个空行。
对于每一个数据,如果找不到解,则输出一个空行。如果找到解,就把符合条件的所有直角三角形输出。每个三角形占一行,输出该三角形的另外两条边,
必须先输出长边,然后一个逗号,再输出短边。两个三角形之间不能有空行,而且必须按照长边降序排列。
输入样例
2
20
12
输出样例
101,99
52,48
29,21
25,15
16,12
37,35
20,16
15,9
13,5
#include<stdio.h>
#include<iostream>
using namespace std;
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int n,i,w=0;
cin>>n;
int f=n*n;
for(i=1;i<=n*n;i++)
{
if(f%i==0&&(f/i-i)>0&&(f/i-i)%2==0)
{
printf("%d,%d\n",(f/i+i)/2,(f/i-i)/2);
w=1;
}
}
int j;
for(i=1;i<n;i++)
{
for(j=i;j<n;j++)
{
if(i*i+j*j==f)
printf("%d,%d\n",j,i);
w=1;
}
}
if(w==0)
printf("\n");
printf("\n");
}
return 0;
}
#include<stdio.h>
#include<iostream>
#include<math.h>
using namespace std;
int main()
{
int t;
cin>>t;
while(t--)
{
int n,w=0;
cin>>n;
int f=n*n;
for(int i=1;i<=n*n;i++)
{
if(f%i==0&&(f/i-i)>0&&(f/i-i)%2==0)
{
printf("%d,%d\n",(f/i+i)/2,(f/i-i)/2);
w=1;
}
}
for(int i=1;i<n;i++)
{
for(int j=i;j<n;j++)
{
if(i*i+j*j==f)
{
printf("%d,%d\n",j,i);
w=1;
}
}
}
if(w=0) cout<<endl;
cout<<endl;
}
return 0;
}
8623 龙龙
该题有题解
时间限制:1000MS 代码长度限制:10KB
提交次数:664 通过次数:118
题型: 编程题 语言: G++;GCC
Description
在比赛的时候,1Y(1 次AC)是很值得高兴的事情。但很多大牛总会因为很弱智的错误先WA 一次,再AC。
而很多时候,这点罚时的差距使得他们与金牌无缘。弱智错误系列中最显著的就是忘记加龙龙。
龙龙外国人叫它作long long,表示64位整数,输入与输出64位整数则可以使用例如
scanf("%lld", &a)与printf("%lld", a)的形式完成。很多图论和动态规划的题目中,
虽然题目说最后输出的答案是32 位的整数,但中间计算的过程有时会超过int,这时我们就要使用龙龙了。
可惜的是,很多同学刚开始学写程序都是用VC的,在VC上是无法使用long long的,我们要用__int64
代替,输入与输出64位整数则可以使用例如scanf("%I64d", &a)与printf("%I64d", a)的形式完成。
但是提交上OJ 的时候,如果使用GCC或G++,都只支持long long,我们在提交时又得按照上边的改回来(的确挺麻烦,窘)。
为了让知道龙龙的同学们记得使用龙龙,不知道的学习使用龙龙,下边有个很简单的函数,希望大家
求出它的返回值:
long long H(int n){
long long res = 0;
int i;
for(i = 1; i <= n; i=i+1 ){
res = (res + n/i);
}
return res;
}
不过直接使用这个函数是会超时的,必须改造这个函数,当然这一定难不到未来的编程高手--你
输入格式
第一行是数字T(T<=1021)表示case数,接下来T 行,每行一个整数n,n是一个32 位整数(保证可以由int 表示)。
输出格式
函数返回值。
输入样例
2
5
10
输出样例
10
27
#include<iostream>
#include<cstring>
#include <cstio>
using namespace std;
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int n;
scanf("%d",&n);
long long ans=0;
long long now=1,sum=0;
if(n>0)
{
while(1)
{
int x=n/now;
int y=n/(now+1);
if(x==y)
{
break;
}
ans+=now*(x-y);
sum+=x-y;
now++;
}
for(int i=1;i<=n-sum;i++)
{
ans=ans+n/i;
}
}
cout<<ans<<endl;
}
return 0;
}
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int main()
{
int t;
cin>>t;
while(t--)
{
int n;
cin>>n;
long long ans=0;
long long now=1,sum=0;
if(n>0)
{
while(1)
{
int x=n/now;
int y=n/(now+1);
if(x==y)
{
break;
}
ans+=now*(x-y);
sum+=x-y;
now++;
}
for(int i=1;i<=n-sum;i++)
{
ans=ans+n/i;
}
}
cout<<ans<<endl;
}
return 0;
}
*/
18444 分数拆分
时间限制:2500MS 代码长度限制:10KB
提交次数:0 通过次数:0
题型: 编程题 语言: G++;GCC;VC
Description
输入正整数k(k<=1000),将1/k变为不少于2项,但不多于3项的1/(xi)之和,xi为正整数,且i表示序号
注:请使用long long
输入格式
多case,一行一个整数k
最后一行是0
输出格式
对每一个case,按等式最右边一项分母,由小到大排序输出满足条件的等式,最右边一项分母相同,则按最右边第二项,依次类推
每一个case完成后,输出一个空行(没有满足的等式时,也要输出该空行)
输入样例
2
3
4
0
输出样例
1/2=1/6+1/3
1/2=1/42+1/7+1/3
1/2=1/24+1/8+1/3
1/2=1/18+1/9+1/3
1/2=1/15+1/10+1/3
1/2=1/12+1/12+1/3
1/2=1/4+1/4
1/2=1/20+1/5+1/4
1/2=1/12+1/6+1/4
1/2=1/8+1/8+1/4
1/2=1/10+1/5+1/5
1/2=1/6+1/6+1/6
1/3=1/12+1/4
1/3=1/156+1/13+1/4
1/3=1/84+1/14+1/4
1/3=1/60+1/15+1/4
1/3=1/48+1/16+1/4
1/3=1/36+1/18+1/4
1/3=1/30+1/20+1/4
1/3=1/28+1/21+1/4
1/3=1/24+1/24+1/4
1/3=1/120+1/8+1/5
1/3=1/45+1/9+1/5
1/3=1/30+1/10+1/5
1/3=1/20+1/12+1/5
1/3=1/15+1/15+1/5
1/3=1/6+1/6
1/3=1/42+1/7+1/6
1/3=1/24+1/8+1/6
1/3=1/18+1/9+1/6
1/3=1/15+1/10+1/6
1/3=1/12+1/12+1/6
1/3=1/21+1/7+1/7
1/3=1/12+1/8+1/8
1/3=1/9+1/9+1/9
1/4=1/20+1/5
1/4=1/420+1/21+1/5
1/4=1/220+1/22+1/5
1/4=1/120+1/24+1/5
1/4=1/100+1/25+1/5
1/4=1/70+1/28+1/5
1/4=1/60+1/30+1/5
1/4=1/45+1/36+1/5
1/4=1/40+1/40+1/5
1/4=1/12+1/6
1/4=1/156+1/13+1/6
1/4=1/84+1/14+1/6
1/4=1/60+1/15+1/6
1/4=1/48+1/16+1/6
1/4=1/36+1/18+1/6
1/4=1/30+1/20+1/6
1/4=1/28+1/21+1/6
1/4=1/24+1/24+1/6
1/4=1/140+1/10+1/7
1/4=1/42+1/12+1/7
1/4=1/28+1/14+1/7
1/4=1/8+1/8
1/4=1/72+1/9+1/8
1/4=1/40+1/10+1/8
1/4=1/24+1/12+1/8
1/4=1/16+1/16+1/8
1/4=1/36+1/9+1/9
1/4=1/18+1/12+1/9
1/4=1/20+1/10+1/10
1/4=1/15+1/12+1/10
1/4=1/12+1/12+1/12
#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long ll;
int main()
{
ll k,n;
while(scanf("%lld",&n)!=-1)
{
for(ll i=n+1;i<=n*3;i++)
{
for(ll j=max(i,(-i*n)/(n-i));j<=(2*n*i)/(i-n);j++)
{
if(i*j==n*(i+j))
{
printf("1/%lld=1/%lld+1/&lld\n",n,j,i);
}
else if((n*i*j)%(i*j-n*i-n*j)==0&&(i*j-n*i-n*j)>0)
{
printf("1/%lld=1/%lld+1/%lld+1/%lld\n",n,(n*i*j)/(i*j-n*i-n*j),j,i);
}
}
}
printf("\n");
}
return 0;
}
#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long ll;
int main()
{
ll i,j,k,n;
while(scanf("%lld",&n)!=-1)
{
for(i=n+1;i<=n*3;i++)//最后一位
{ //由i来确定j的起始
for(j=max(i,(-i*n)/(n-i));j<=(2*n*i)/(i-n);j++)//倒数第二位,max函数用于解决重复问题,防止后面的数字比前面的还大,那就和前面的重复了
{
if(i*j==n*(i+j))//当前i和j之和就已经足以满足1/n
{
printf("1/%lld=1/%lld+1/%lld\n",n,j,i);
}
else if((n*i*j)%(i*j-n*i-n*j)==0&&(i*j-n*i-n*j)>0)//观察第一位分数能否被约分以此保证分子为1
{ //这里是利用1/n=1/i+1/j+1/k把k单独表示出来的
printf("1/%lld=1/%lld+1/%lld+1/%lld\n",n,(n*i*j)/(i*j-n*i-n*j),j,i);//第二个输出是用来约分到最简,使分子为一
}
}
}
printf("\n");
}
return 0;
}
18124 N皇后问题
时间限制:5000MS 代码长度限制:10KB
提交次数:0 通过次数:0
题型: 编程题 语言: G++;GCC;VC
Description
有N*N的国际象棋棋盘,要求在上面放N个皇后,要求任意两个皇后不会互杀,有多少种不同的放法?
输入格式
每一个数为T,代表CASE的数量,T<=13
此后,每行一个数N(13>=N>0)
输出格式
每一个CASE,输出对应答案
输入样例
2
4
5
输出样例
2
10
#include<cstdiio>
#include<iostream>
#include<cstring>
using namespace std;
int N,result;
int row[15]={0};
void dfs(int index)
{
if(index==N)
{
result++;
return;
}
int i,j;
for(i=0;i<n;i++)
{
row[index]=i;
for(j=0;j<index;j++)
if(row[index]==row[j]||row[index]-index=row[j]-j||row[index]+index==row[j]+j)
break;
if(j==index) dfs(index+1);
}
}
int main()
{
int T;
cin>>T;
while(T--)
{
memset(row,0,sizeof(row));
result=0;
cin>>N;
dfs(0);
cout<<result<<endl;
}
return 0;
}
#include <cstdio>
#include <iostream>
#include <cstring>
using namespace std;
int N, result;
int row[15] = {0};//row[i] = j;第i行第j列放了皇后
void dfs(int index)
{
if (index==N)
{
result++;
return;
}
int i, j;
for (i = 0; i < N; i++)//尝试放每一列//从0列放到第N-1列,每一列都尝试放一下,如果可以放,则继续探索下一行可以放在哪列
{
row[index] = i;
for (j = 0; j < index; j++)//遍历当前index行前面每行的皇后跟此行的皇后进行判断,看看有没有纵向冲突和斜向冲突
if (row[index] == row[j] || row[index] - index == row[j] - j || row[index] + index == row[j] + j)
break;
if (j == index)//判断有没有冲突,如果没有,则继续深搜
dfs(index+1);
}
}
int main()
{
int T;
cin>>T;
while (T--)
{
memset(row,0,sizeof(row));
result = 0;
cin>>N;
dfs(0);
cout<<result<<endl;
}
return 0;
}
19010 最小的特殊数字
时间限制:1000MS 代码长度限制:10KB
提交次数:0 通过次数:0
题型: 编程题 语言: G++;GCC;VC;JAVA
Description
用全部N(N<=10)个0-9的数字组成一个“有效”整数(即没有前置0的整数),
求这些组成的数中能被K(0<K<10^10)整除的最小数字。
输入格式
输入分两行,第一行输入N, K,第二行输入N个数字。
输出格式
输出满足条件的最小的数(不含前置0),如果没有满足条件的数输出 -1。
输入样例
4 7
4 0 1 3
输出样例
1043
提示
413 % 7 = 0, 但是有前置0,所以满足条件的最小数是 1043 % 7 = 0。
此类题目需注意特殊情况,比如n=1时,如只输入一个0,答案只能是0。
注意long long
#include<iostream>
#include<string>
#include<algorithm>
using namespace std;
#define long long ll;
ll N;//几个数字
ll K;//除数
ll ans=0; //满足条件的最小的数(不含前置0)
ll a[15];//存放输入的n个数字
ll b[15];//存放dfs结果的每一位数字
ll book[15]; //标记数组
ll getNum()
{
ll num=0;
for(int i=1;i<=n;i++)
{
num=num*10+b[i];
}
return num;
}
void dfs(int step)
{
if(step==n+1)
{
if(getNum()%k==0&&ans==0)//!!!必须加上ans==0
{
ans=getNum();
}
return; /*
注意这个 return 它的作用不是返回主函数,而是返回上一级的dfs函数
例:如果此时是 dfs(5),遇到这个 return 就会回到上一级的 dfs函数
也就是dfs(4),但此时dfs(4)的大部分语句已经执行了,只需要接着执行 book[i]=0
然后继续进入for循环进入下一次的 dfs函数,直到结束。*/
}
for(int i=1;i<=n;i++)
{
if(a[i]==0&&step==1)
{
continue;
}
if(book[i]==0)
{
b[step]=a[i];
book[i]=1;
dfs(step+1);
book[i]=0;
}
}
}
int main()
{
cin>>N>>K;
for(int i=1;i<=N;i++)
{
cin>>a[i];
}
if(N==1&&a[1]==0)
{
cout<<"0"<<endl;
}
else
{
sort(a+1,a+n+1); // //数组下标从1开始
dfs(1);
if(ans==0)
{
cout<<"-1"<<endl;
}
else
{
cout<<ans<<endl;
}
}
return 0;
}
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
#define long long ll;
ll N;
ll K;
ll ans;
ll a[15];
ll b[15];
ll book[15];
ll getnum()
{
ll num=0;
for(int i=1;i<=N;i++)
{
num=num*10+b[i];
}
return num;
}
void dfs(int step)
{
if(step==N+1)
{
if(getnum()%K==0&&ans==0)
{
ans=getnum();
}
return;
}
for(int i=1;i<=N;i++)
{
if(a[i]==0&&step==1)
{
continue;
}
if(book[i]==0)
{
b[step]=a[i];
book[i]=1;
dfs(step+1);
book[i]=0;
}
}
}
int main()
{
cin>>N>>K;
for(int i=1;i<=N;i++)
{
cin>>a[i];
}
if(N==1&&a[1]==0)
{
cout<<'0''<<endl;
}
else
{
sort(a+1,a+N+1);
dfs(1);
if(ans==0)
{
cout<<'-1'<<endl;
}
else
{
cout<<ans<<endl;
}
}
return 0;
}
8615 快乐
该题有题解
时间限制:500MS 代码长度限制:10KB
提交次数:312 通过次数:98
题型: 编程题 语言: G++;GCC
Description
Lian是一个喜欢看动画片的人,自从成为ACMer(ACM爱好者)之后,他又迷上了网上做题。做题让他快乐,不过这也是需要付出精力的!!
假设有n道题,Lian做出第i道题后,他可以获得的快乐指数将增加gethappy[i],而消耗掉的精力将是losspow[i]。
假设Lian初始的快乐指数为1,精力为2000。可以理解,如果他消耗完了所有的精力那他得到再多的快乐都没有用。
你的任务就是帮他计算他所能得到的最多的快乐指数,且最后他依然有多余的精力(即至少为1)。
输入格式
第一行输入一个整数n,表示有n道题。(n<=50)
第二行输入n个整数,表示gethappy[1]到gethappy[n]
第三行输入n个整数,表示losspow[1]到losspow[n]。
输出格式
一个整数,表示Lian所能获得的最大快乐指数。
输入样例
3
15 23 61
350 1301 1513
输出样例
77
#include<iosyream>
#include<string.h>
#include<algorithm>
using namespace std;
int main()
{
int F[51][2001]={0};
memset(F,0,sizeof(F));
int n;
cin>>n;
int gethappy[n+1];
int losspow[n+1];
for(int i=1;i<=n;i++)
{
cin>>gethappy[i];
}
for(int i=1;i<=n;i++)
{
cin>>losspow[i];
}
for(int i=0;i<=n;i++)
{
for(int j=1;j<=2000;j++)
{
if(losspow[i]>j)
{
F[i][j]=F[i-1][j];
}
else if(losspow[i]<j)
{
F[i][j]=max(F[i-1][j],F[i-1][j-losspow[i]]+gethappy[i]);
}
}
}
cout>>F[n][2000]+1<<endl;
return 0;
}
18705 01背包问题
时间限制:1000MS 代码长度限制:10KB
提交次数:0 通过次数:0
题型: 编程题 语言: 不限定
Description
有一个容积为M的背包和N件物品。第i件物品的体积W[i],价值是C[i]。求解将哪些物品装入背包可使价值总和最大。每种物品只有一件,
可以选择放或者不放入背包。
输入格式
第一行:两个整数,M(背包容量,M<=200)和N(物品数量,N<=30);
第2..N+1行:每行二个整数Wi,Ci,表示每个物品的重量和价值。
输出格式
一个数,表示最大总价值。
输入样例
10 4
2 1
3 3
4 5
7 9
输出样例
12
#include<iostream>
using namespace std;
int main()
{
int m,n;
cin>>m>>n;
int w[50][2];
int b[20][2];
for(int i=1;i<=n;i++)
{
cin>>w[i][0]>>w[i][1];
}
for(int i=0;i<=m;i++)
{
b[0][i]=0;
}
for(int i=1;i<=n;i++)
{
for(j=1;j<=m;j++)
{
if(j<w[i][0])
{
b[i][j]=b[i-1][j];
}
else
{
b[i][j]=max(b[i-1][j],b[i-1][j-w[i][0]]+w[i][1]);
}
}
}
cout>>b[n][m]<<endl;
return 0;
}
19523 最长上升子序列长度
时间限制:1000MS 代码长度限制:10KB
提交次数:0 通过次数:0
题型: 编程题 语言: 不限定
描述:
当元素 ai1 < ai2 < … < aiK. 就说这个序列是有序上升的。
给定序列(a1, a2, …, aN),存在许多这样的子序列(ai1, ai2, …, aiK),
其中1 <= i1 < i2 < … < iK <= N.
也就是说,子序列是原序列允许挑选若干不连续的元素形成的序列。
举个例子,序列 (1, 7, 3, 5, 9, 4, 8) 就有许多个上上子序列,比如(1, 7), (3, 4, 8) 等。
所有这些上升子序列中最长的长度为4,比如 (1, 3, 5, 8).
你来编程实现,当给定一个初始序列,求解这个序列的最长上升子序列的长度。
输入格式:
此例包含多个测试cases(少于100组test cases)。
每一组test case包含2行。
第一行是这组case的序列长度 N。(N的范围0~10000)
第二行包含 N个整数的一个序列,用空格间隔这N个整数, 1 <= N <= 10000。
当N为0时,表示测试结束。
输出格式:
输出必须对每个test case,都有一个整数结果,表示这组case的最长上升子序列的长度。
输入样例:
7
1 7 3 5 9 4 8
6
1 8 3 6 5 9
5
1 2 3 4 5
0
输出样例:
4
4
5
#include<iostream>
using namespace std;
int main()
{
int n;
while(cin>>n&&n)
{
int s[10005]={0};
int length[10005]={0};
int res=0;
for(int i=1;i<=n;i++)
{
cin>>s[i];
}
for(int i=1;i<=n;i++)
{
int m=1;
for(int j=1;j<i;j++)
{
if(s[j]<s[i]&&length[j]+1>m)
{
m=length[j]+1;
}
}
length[i]=m;
if(res<length[i])
res=length[i];
}
cout<<length[i]<<endl;
}
}
#include<iostream>
using namespace std;
int main()
{
int n=0;
while(cin>>n&&n)
{
int ss[10005]={0};
int length[10005]={0};
int res=0;
for(int i=1;i<=n;i++)
{
cin>>ss[i];
}
for(int i=1;i<=n;i++)
{
int m=1;
for(int j=1;j<i;j++)
{
if(ss[j]<ss[i]&&length[j]+1>m)
{
m=length[j]+1;
}
}
length[i]=m;
if(res<length[i])
res=length[i];
}
cout<<res<<endl;
}
return 0;
}
18308 最长公共子序列长度
时间限制:1000MS 代码长度限制:10KB
提交次数:0 通过次数:0
题型: 编程题 语言: G++;GCC;VC
Description
给定两个字符串,请输出这两个字符串的最大公共子序列
输入格式
两行,一行一个字符串(不包括空格,Tab键),长度不超过1000
输出格式
输出最大公共子序列的长度
输入样例
abbca
aba
输出样例
3
#include<iostream>
#include<string.h>
using namespace std;
int main()
{
string a,b;
static int dp[1005][1005];
cin>>a>>b;
for(int i=1;i<=a.size();i++)
{
for(int j=0;j<=b.size();j++)
{
if(a[i-1]==b[j-1])
{
dp[i][j]=dp[i-1][j-1]+1;
}
else
{
dp[i][j]=max(dp[i-1][j],dp[i][j-1]);
}
}
}
cout<<dp[a.size()][b.size()]endl;
return 0;
}
18233 万湖之国的形成
时间限制:2500MS 代码长度限制:10KB
提交次数:0 通过次数:0
题型: 编程题 语言: G++;GCC;VC
Description
N国原是一块平原上,没有湖,直到一颗小行星撞入大气层碎成成千上万的碎片,碎片再撞击地面形成
一个一个的坑, 下雨之后,最终形成万湖之国。
现在科学家想用计算机模拟万湖之国形成过程,假设每一块碎片撞击地面,都撞出一个园形坑,现在知道
每一个碎片造成的坑的圆心和半径,问每个坑都注满水后,最终形成多少个湖?
输入格式
第一行一个整数N,1<=N<=100,000,表示坑的数量
此后N行,每一行三个double实数,前两个数是圆心的坐标x和y,最后一个数是圆半径(不大于1000)
(数据随机产生,分布均匀)
输出格式
湖的个数
输入样例
3
0 0 5
10 0 5
11.1 0 2.5
输出样例
2
#include <iostream>
#include <algorithm>
using namespace std;
int book[100050]; //标记数组
struct Circle
{
double x;
double y;
double r;
};
Circle circle[100050];
bool compare(Circle a,Circle b)
{
return a.x+a.r<b.x+b.r; //以圆的右端点排序
}
int Find(int k)
{
if(book[k]==k) return k; //如果没有被合并过,返回父节点的值
else return book[k]=Find(book[k]); //如果该圆坑被合并过,找到父节点的值
// !!!return book[k]=Find(book[k])
}
int main()
{
int n;
int num;
cin>>n;
num=n;
for(int i=0; i<n; i++)
{
cin>>circle[i].x>>circle[i].y>>circle[i].r;
book[i]=i; //一开始,每个圆坑都是自己的父节点,i就是父节点的值
}
sort(circle,circle+n,compare);
for(int i=0; i<n; i++)
{
for(int j=i-1; j>=0; j--)
{
if(circle[j].x+circle[j].r<=circle[i].x-circle[i].r)
{
break;
}
if(((circle[j].x-circle[i].x)*(circle[j].x-circle[i].x)+(circle[j].y-circle[i].y)*(circle[j].y-circle[i].y))<(circle[j].r+circle[i].r)*(circle[j].r+circle[i].r))
{
int m,n;
m=Find(i); //找到i父节点的值
n=Find(j); //找到j父节点的值
if(m!=n) //如果i,j父节点的值不同
{
num--; //圆坑数量-1
book[m]=n; //再把两个圆坑合并为1个,父节点的值改为同一个
}
}
}
}
cout<<num<<endl;
return 0;
}
18130 繁忙的公路
时间限制:6000MS 代码长度限制:10KB
提交次数:0 通过次数:0
题型: 编程题 语言: G++;GCC
Description
在一条笔直的大道(单方向行车道)上,汽车川流不息。道路从起点到终点,等距离的标记了1到N,
即起点是1,然后分别是2、3、4.....,终点是N。每一个标记处,安装了智能探头,可以感知
在该点处车辆的增减数量。
一开始,整条道路上,没有车,然后,是不断接收到的智能探头发回的信息,格式如下:
H 5 9
H表明收到的是智能探头的回传信息,5表示标记5处的车辆信息,9表示该处车辆增加了9辆。
同时,在某个时刻,需要查询在一段连续的道路上,共有多少辆车
查询格式如下:
Q 3 10
Q表明收到的是查询,3是起点,10是终点(包括3和10两处)
要求编程实现正确处理上述信息处理和查询
输入格式
第一行一个整数N(1<=N<=1,000,000),表示标记范围是1到N
第二行一个整数M(1<=M<=100,000),表示探头信息(或查询)的总数量
此后M行,每行一个探头信息或查询请求
输出格式
每逢遇到查询的时候,输出查询范围内的有多少辆车,占一行,查询结果最大不超过2的63次方
输入样例
10
4
H 5 10
Q 1 10
H 6 20
Q 1 10
输出样例
10
30
提示
开始时,整条路上没有车辆
#include<iostream> #include<algorithm> #include<cstdio> using namespace std; #define long long ll; ll d[1000001]; ll N,M; ll lowbit(ll x) { return x&(-x); } void updata(ll i,ll num) { while(i<=N) { d[i]+=num; i+=lowbit(i); } } ll getnum(ll i) { ll s=0; while(i>0) { s+=d[i]; i-=lowbit(i); } return s; } int main() { cin>>N>>M; for(int i=1;i<=N;i++) { d[i]=0; } for(int i=0;i<M;i++) { char ch; ll s1,s2; cin>>ch>>s1>>s2; if(ch=='H') updata(s1,s2); if(ch=='Q') cout<<getnum(s2)-getnum(s1-1)<<endl; } return 0; }