这套题目简单的是真简单,复杂的也是真不好写。尤其是后三道,奔溃啊。
A-GRE(水题)
#include <iostream>
#include <stdio.h>
#include <string>
#include <map>
using namespace std;
map<string,string>m;
void init() {
m["zero"] = "ling";
m["one"] = "yi";
m["two"] = "er";
m["three"] = "san";
m["four"] = "si";
m["five"] = "wu";
m["six"] = "liu";
m["seven"] = "qi";
m["eight"] = "ba";
m["nine"] = "jiu";
m["ten"] = "shi";
}
int main() {
int t;
cin>>t;
init();
string str;
while(t--) {
cin>>str;
cout<<m[str]<<endl;
}
return 0;
}
B-Words Game(水题)
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
char str[1000000];
int vis[30];
int main() {
while(~scanf("%s",str)) {
memset(vis,0,sizeof(vis));
for(int i = 0; i < strlen(str); i++) {
vis[str[i]-'a'] = 1;
}
int ans = 0;
int n;
scanf("%d ",&n);
while(n--) {
scanf("%s",&str);
bool flag = true;
int len = strlen(str);
for(int i = 0; i < len; i++) {
if(vis[str[i]-'a']==0) {
flag = false;
break;
}
}
if(flag) {
ans = max(ans,len);
}
}
printf("%d\n",ans);
}
return 0;
}
C-Arch0n's interesting game(水题)
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
int a[2600],b[5000000];
bool cmp(int n1,int n2) {
return n1>n2;
}
int main() {
int t,n,k;
scanf("%d",&t);
while(t--) {
scanf("%d%d",&n,&k);
for(int i = 0; i < n; i++) {
scanf("%d",&a[i]);
}
int cnt = 0;
for(int i = 0; i < n; i++) {
for(int j = i+1; j < n; j++) {
b[cnt++] = min(a[i],a[j]);
}
}
sort(b,b+cnt,cmp);
printf("%d\n",b[k-1]);
}
return 0;
}
D-另一个另一个简单游戏(水题)
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
int arr[1000];
int main() {
int n,t;
scanf("%d",&t);
while(t--) {
scanf("%d",&n);
long long sum = 0;
for(int i = 0; i < n; i++) {
scanf("%d",&arr[i]);
sum += arr[i];
}
printf("%d\n",sum/n);
}
return 0;
}
E-Xiedly And His Password
/*********************
Date 2018/4/22
Author Ms. Wen
解题思路:
动态规划,dp[i][j]用来代表以i处字符为结尾的值模
3后为j的值的个数。有一点,不知道为什么,直接用
strlen求字符串长度提交后,就是一直出错,拿一个
变量承接一下就没问题了。
****************************/
#include <iostream>
#include <stdio.h>
#include <string.h>
using namespace std;
typedef long long ll;
const int maxn = 1e6+10;
char str[maxn];
ll dp[maxn][4];
int main() {
while(~scanf("%s",str)) {
ll ans = 0;
dp[0][0] = dp[0][1] = dp[0][2] = 0;
if(str[0]=='0') {
dp[0][0] = 1;
ans++;
}
else {
dp[0][1] = 1;
}
int len = strlen(str);
for(int i = 1; i < len; i++) {
if(str[i]=='0') {
dp[i][0] = dp[i-1][0]+1;
dp[i][2] = dp[i-1][1];
dp[i][1] = dp[i-1][2];
}
else {
dp[i][1] = dp[i-1][0]+1;
dp[i][0] = dp[i-1][1];
dp[i][2] = dp[i-1][2];
}
ans += dp[i][0];
}
printf("%lld\n",ans);
}
return 0;
}
F-Operating System
/********************
Date 2018/4/21
Author Ms. Wen
解题思路:这个题目属于计算机组成原理中的一个经典问题,遇到需要的东西
先到内存找,内存有,则命中,否则看内存是否满,未满,将内容从外存装入
内存,否则需要一定的替换算法去适当的替换内存中的某块。本题难点在于:
替换策略的设计。
基本思路:使用数组vis标记某编号的内容是否在内存中,如果在,不必考虑。
如果不再,则看cnt变量的值,cnt代表当前内存中被占了多少块,如果cnt<n,
即未满,则标记新调入的块,cnt加1,且ans加1。如果cnt==n。则考虑找此后
出现次数最少的那些块,替换它。这点可以想想,此刻之后,假如有些块将来要
用10次,而有些块将来要用2次,我们当然尽可能的把2次的这个块换掉。
变量含义:
n,m,q:n内存块数,m外存块数,q是q次调用。
vis:vis[i]用来标记i在内存中是否存在。
arr:arr用来存放q次调用的块的编号。
v:v[0]用来存放块的编号,v[i]用来存放调用i的时间,其时间在容器中倒着存放
*********************/
#include <iostream>
#include <stdio.h>
#include <vector>
#include <string.h>
using namespace std;
const int maxn = 50010;
int n,m,q;
int vis[maxn];
int arr[maxn];
vector<int>v[maxn];
int main() {
while(~scanf("%d%d%d",&n,&m,&q)) {
for(int i = 0; i <= m; i++) {
v[i].clear();
}
int cnt=0,ans=0;
memset(vis,0,sizeof(vis));
for(int i = 1; i <= q; i++) {
scanf("%d",&arr[i]);
if(vis[arr[i]]==0) {
vis[arr[i]] = 1;
v[0].push_back(arr[i]);
}
}
for(int i = q; i > 0; i--) {
v[arr[i]].push_back(i); //倒着压进时间
}
memset(vis,0,sizeof(vis));
for(int i = 1; i <= q; i++) {
int x = arr[i];
//内存中已经存在,不考虑
if(vis[x]==1) continue;
if(cnt<n) {
//不存在,但内存未满
vis[x] = 1;
v[x].pop_back();
cnt++;
ans++;
}
else { //内存满,需要替换。
int y,a,b,t;
a = maxn;
for(int j = 0; j < (int)v[0].size(); j++) {
y = v[0][j];
t = v[y].size();
if(t<a) {
a = t;
}
}
vis[a]=0;
vis[x]=1;
ans++;
}
}
printf("%d\n",ans);
}
return 0;
}
G-小国的复仇
#include <iostream>
#include <stdio.h>
#include <string.h>
using namespace std;
const int maxn = 1e6+10;
const int inf = 0x3f3f3f3f;
int ans[maxn];
int prime[maxn];
void init() {
memset(prime,0,sizeof(prime));
ans[1] = 0;
for(int i = 2; i <= 1e6; i++) {
if(prime[i]==0) {
ans[i] = i-1;
for(int j = 2*i; j <= 1e6; j+=i) {
prime[j] = 1;
int tmp = j;
while(tmp%i==0) {
ans[j] += ans[i];
tmp = tmp/i;
}
}
}
}
}
int main() {
int n,t;
init();
scanf("%d",&t);
while(t--) {
scanf("%d",&n);
printf("%d\n",ans[n]);
}
return 0;
}
H-敬老师的手环II
I-Tr0y And His Startup
/**
假如L,R范围遭到流量袭击。则对于L,R中的任意一个假设为i。
其最终导入第三方服务其的流量是:Sum(x[i],x[i]+1,..,C-1,C)
然后用等差数列求和:(x[i]+C)*(C-x[i]+1) / 2.
(x[i]+C)*(C-x[i]+1) = C*(C+1) - x[i]*(x[i]-1);
因为i属于【L,R】。所以答案为(C*(C+1)*(R-L+1)-Sum((x[L]*(x[L]-1))+...(x[R]*(x[R]-1))))/(2*C);
所以只需要用线段树维护,Sum的值即可。
*/
#include <iostream>
#include <stdio.h>
#include <string.h>
#define lchild left,mid,root<<1
#define rchild mid+1,right,root<<1|1
using namespace std;
typedef long long LL;
const int maxn = 1e5+10;
const int mod = 1e9+7;
LL x[maxn<<2],lazy[maxn<<2],sum[maxn<<2];
//更新当前节点的值。
void push_up(int root) {
x[root] = x[root<<1] + x[root<<1|1];
sum[root] = sum[root<<1] + sum[root<<1|1];
}
//下推标记
void push_down(int left,int right,int root) {
if(lazy[root]) {
int lroot = root<<1;
int rroot = root<<1|1;
int mid = (left+right)/2;
//下推标记到左孩子。
sum[lroot] = sum[lroot] + 2*lazy[root]*x[lroot] + lazy[root]*(lazy[root]-1)*(mid-left+1);
x[lroot] = x[lroot] + lazy[root]*(mid-left+1);
lazy[lroot] += lazy[root];
//下推标记到右孩子。
sum[rroot] = sum[rroot] + 2*lazy[root]*x[rroot] + lazy[root]*(lazy[root]-1)*(right-mid);
x[rroot] = x[rroot] + lazy[root]*(right-mid);
lazy[rroot] += lazy[root];
//释放根节点的标记。
lazy[root] = 0;
}
}
//构建线段树
void build(int left,int right,int root) {
lazy[root] = x[root] = sum[root] = 0;
if(left == right) {
scanf("%lld",&x[root]);
sum[root] = x[root]*(x[root]-1);
return;
}
int mid = (left+right)/2;
build(lchild);
build(rchild);
push_up(root);
}
//查询和值。
LL query(int L,int R,int left,int right,int root) {
if(L<=left && right<=R) {
return sum[root];
}
push_down(left,right,root);
int mid = (left+right)/2;
LL ans = 0;
if(L<=mid) ans += query(L,R,lchild);
if(R>mid) ans += query(L,R,rchild);
return ans;
}
//给L到R内每个x[i]加add。
void update(int L,int R,int add,int left,int right,int root) {
if(L<=left && right<=R) {
sum[root] = sum[root] + 2*add*x[root] + (LL)add*(add-1)*(right-left+1);
x[root] = x[root] + (LL)add*(right-left+1);
lazy[root] += add;
return;
}
push_down(left,right,root);
int mid = (left+right)/2;
if(L<=mid) update(L,R,add,lchild);
if(R>mid) update(L,R,add,rchild);
push_up(root);
}
//用整数快速幂求乘法逆元。
LL qucikPow(LL n,LL k) {
LL ans,res;
ans = 1;
res = n;
while(k) {
if(k&1) {
ans = ans*res%mod;
}
k = k/2;
res = res*res%mod;
}
return ans;
}
int main() {
int n,c,q;
while(~scanf("%d%d%d",&n,&c,&q)) {
build(1,n,1);
//因为mod是素数,所以可以用小费马定理求2*c模mod的乘法逆元。
LL tmp = qucikPow((LL)2*c,mod-2);
int l,r,add;
while(q--) {
scanf("%d%d%d",&l,&r,&add);
LL ans = query(l,r,1,n,1);
LL C = c;
ans = ((C*C%mod+C)%mod)*(r-l+1)%mod - ans;
ans = ans%mod;
ans = (ans+mod)%mod*tmp%mod;
update(l,r,add,1,n,1);
printf("%lld\n",ans);
}
}
return 0;
}
J-Database
/*******************************
Author Ms.Wen
Date 2018/4/25
解题思路:
就是模拟执行sql语句的过程,按照操作进行模拟,思路是不好讲的。
这个题目写了5个小时。疯了,题目意思很简单,模拟过程很复杂啊。奔溃。
变量含义:
t[][][]:三维数组用来存放表。t就代表数据库
id:用来给表进行编号,这样可以吧表名通过map映射成表编号。
arr:用来给某个表中的列进行编号,这样可以通过map把列名映射成编号。
num:用来记录某个表中的记录条数。
table:用来从表名映射成表编号。
m:用来从列名映射成列编号。
********************************/
#include <iostream>
#include <stdio.h>
#include <vector>
#include <map>
#include <string.h>
#include <set>
using namespace std;
int t[6][6][120];
int id,arr[10],num[10];
map<string,int>table; //映射表名。
map<string,int>m[7]; //映射某表的列名。
set<int>s;
//初始化
void init() {
id = 0;
memset(t,0,sizeof(t));
memset(arr,0,sizeof(arr));
memset(num,0,sizeof(num));
for(int i = 0; i < 5; i++) {
m[i].clear();
}
}
//建表函数
void createTable(string sql) {
int pos;
string tName="";
int len = sql.length();
//求表名
for(int i = 13; i < len; i++) {
if(sql[i]=='(') {
pos = i+1;
break;
}
else {
tName += sql[i];
}
}
table[tName] = id++;
string colName=""; //列名
int tid = table[tName];
//给列进行编号。
for(int i = pos; i < len; i++) {
if(sql[i]==';') break;
if(sql[i]==' ') {
colName = "";
}
else if(sql[i]==','||sql[i]==')') {
m[tid][colName] = arr[tid];
arr[tid]++;
}
else {
colName += sql[i];
}
}
}
//更新表的函数。
void updateTable(string sql) {
string colName[10];
int value[10];
int cnt = 0;
string tName="";
int pos;
int len = sql.length();
//求表名
for(int i = 12; i < len; i++) {
if(sql[i]=='(') {
pos = i+1;
break;
}
else {
tName += sql[i];
}
}
int id = table[tName]; //求表的编号。
//求插入数据的列名
string cName = "";
for(int i = pos; i < len; i++) {
if(sql[i]==')') {
colName[cnt++] = cName;
pos = i + 9;
break;
}
else if(sql[i]==',') {
colName[cnt++] = cName;
}
else if(sql[i]==' ') {
cName = "";
}
else {
cName += sql[i];
}
}
int n = 0;
cnt = 0;
//求插入的值。
for(int i = pos; i < len; i++) {
if(sql[i]==')') {
value[cnt++] = n;
break;
}
else if(sql[i]==',') {
value[cnt++] = n;
}
else if(sql[i]==' ') {
n = 0;
}
else {
n = n*10 + (sql[i]-'0');
}
}
int row = num[id];
int colID;
//插入数据
for(int i = 0; i < cnt; i++) {
colID = m[id][colName[i]];
t[id][colID][row] = value[i];
}
num[id]++; //表的记录数加1.
}
//第一种查询。
void query1(string sql,bool flag) {
int colID[10];
int cnt = 0;
string tName = "";
int len = sql.length();
int pos = sql.find("from");
sql[pos-1] = ',';
//求表名
for(int i = pos+5; i < len; i++) {
if(sql[i]==';') {
break;
}
else {
tName += sql[i];
}
}
int id = table[tName]; //求表号
string colName = "";
//求表头名称
for(int i = 7; i < pos; i++) {
if(sql[i]==',') {
colID[cnt++] = m[id][colName];
}
else if(sql[i]==' ') {
colName = "";
}
else {
colName += sql[i];
}
}
//代表是第三种查询语句。
if(flag) {
int row = num[id];
for(int i = 0; i < row; i++) {
for(int j = 0; j < cnt; j++) {
if(j != 0) {
printf(" ");
}
printf("%d",t[id][colID[j]][i]);
}
printf("\n");
}
printf("\n");
}
else { //说明是第四种查询的嵌套查询。
int row = num[id];
int col = m[id][colName];
s.clear();
for(int i = 0; i < row; i++) {
s.insert(t[id][col][i]);
}
}
}
void query2(string sql,bool flag) {
int pos = sql.find("from"); //求单词from的第一次出现的位置
int len = sql.length();
sql[pos-1] = ',';
string colName[10];
int cnt = 0;
string cName = "";
for(int i = 7; i < pos; i++) {
if(sql[i]==',') {
colName[cnt++] = cName;
}
else if(sql[i]==' ') {
cName = "";
}
else {
cName += sql[i];
}
}
string tName = "";
for(int i = pos+5; i < len; i++) {
if(sql[i]==' ') {
pos = i;
break;
}
tName += sql[i];
}
cName = "";
for(int i = pos+7; i < len; i++) {
if(sql[i]==' ') {
pos = i;
break;
}
cName += sql[i];
}
string subsql; //求嵌套的子sql语句。
for(int i = pos+4; i < len; i++) {
subsql += sql[i];
}
//cout<<subsql<<endl;
//嵌套的是query2
if(subsql.find("where")<subsql.length()) {
query2(subsql,false);
}
else { //嵌套的是query1
query1(subsql,false); //求集合
}
//flag是false,先处理子查询。
if(flag == false) {
set<int>tmpSet;
int tid = table[tName]; //求表编号
int row = num[tid];
int col = m[tid][cName];
for(int i = 0; i < row; i++) {
if(s.count(t[tid][col][i])) {
for(int j = 0; j < cnt; j++) {
int x = m[tid][colName[j]];
tmpSet.insert(t[tid][x][i]);
}
}
}
s.clear();
s = tmpSet;
}
else {
int tid = table[tName];
int row = num[tid];
int col = m[tid][cName];
for(int i = 0; i < row; i++) {
if(s.count(t[tid][col][i])) {
for(int j = 0; j < cnt; j++) {
int x = m[tid][colName[j]];
if(j != 0) {
printf(" ");
}
printf("%d",t[tid][x][i]);
}
printf("\n");
}
}
printf("\n");
}
}
int main() {
init();
string sql;
while(getline(cin,sql)) {
//表示该sql语句是建表操作。
if(sql.find("create")!=string::npos) {
createTable(sql);
}
else if(sql.find("insert")!=string::npos) {
updateTable(sql);
}
else if(sql.find("in")!=string::npos) {
query2(sql,true);
}
else {
query1(sql,true);
}
}
return 0;
}
/*
create table wussy(c1, c2, c3);
insert into wussy(c1, c2) values(1, 2);
select c1, c2, c3 from wussy;
insert into wussy(c1, c2, c3) values(4, 5, 6);
create table vampireweekend(c1, c2);
insert into vampireweekend(c1) values(1);
select c1, c2, c3 from wussy;
select c1, c2 from wussy where c1 in select c1 from vampireweekend;
*/