sdutoj 3560 - 3570 http://acm.sdut.edu.cn/sdutoj/problem.php?page=26
A
水题
#include<iostream>
#include<cstdio>
#define mem(a,x) memset(a,x,sizeof(a))
using namespace std;
typedef long long ll;
const int N = 100010;int a[5];
int main(){
int t;
scanf("%d",&t);
while(t--){
int a,b;scanf("%d%d",&a,&b);
printf("%d\n",a/b + (a%b!=0));
}
return 0;
}
B
二分,每次在FIb中找与当前所需数最接近的。。
//好吧,我们当时就是这么做的
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#define mem(a,x) memset(a,x,sizeof(a))
using namespace std;
typedef long long ll;
const int N = 100010;int a[5];
char s[50];
int f[111];
int ans[111];
int main(){
int t;
scanf("%d",&t);
f[0] = 1; f[1] = 2;
int r =0;
for(int i=2;;i++){
f[i] = f[i-1] + f[i-2];
if(f[i-2] + f[i-1] > 1e9) {
r = i;
break;
}
}
//cout<<r<<endl;
while(t--){
mem(ans,0);int l = 0;
int n;scanf("%d",&n);
printf("%d=",n);
int rear = n;
int fir = 1;
while(rear){
int po = lower_bound(f,f+r,rear) - f;
if(po!=0 && f[po] > rear) po--;
ans[l++] = f[po];
rear-= f[po];
}
sort(ans,ans+l);
for(int i=0;i<l;i++){
if(i!=l-1)
printf("%d+",ans[i]);
else
printf("%d\n",ans[i]);
}
}
return 0;
}
C,简单的最短路。
让你找能否从节点n+1连通到节点0,不能输出-1。如果能,则找出从节点n+1到节点0最短的那条通路,输出这条通路中与0相连的节点序号。如果有多条通路,输出节点序号最小的那个,如果n+1节点与0节点直接相连,并且路径也是最短,则输出0;
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<queue>
#include<cstring>
#define mem(a,x) memset(a,x,sizeof(a))
#define INF 0x3f3f3f3f
using namespace std;
typedef long long ll;
const int MAXN = 2020;
int n,m;
struct node{
int v, len;
bool operator < (const node & t) const{
return len > t.len;
}
node(int v = 0, int len = 0):v(v), len(len){}
}tp[MAXN];
vector<node> G[MAXN];
bool vis[MAXN];
int dis[MAXN];
void Init(int n){
for(int i = 0; i <= n; i++){
vis[i] = false;
G[i].clear();
dis[i] = INF;
}
}
int dijstra_heap(int s){
priority_queue<node>Q;
dis[s] = 0;
//vis[s] = 1;
Q.push(node(s,0));
while(!Q.empty()){
node now = Q.top();
Q.pop();
int v = now.v;
if(vis[v]) continue;
vis[v] = true;
for(int i=0;i<G[v].size();i++){
int v2 = G[v][i].v; int len = G[v][i].len;
if(!vis[v2] && dis[v] + len <dis[v2]){
dis[v2] = dis[v] + len ;
//cout<<" ss"<<dis[v2]<<endl;
Q.push(node(v2,dis[v2])); //讲 dis[v2]放入堆中,利用logn的效率找到
//距离最短的节点
}
}
}
return dis[0];
}
int main(){
int t;scanf("%d",&t);
while(t--){
scanf("%d%d",&n,&m);
Init(n+1);int l = 0;
int a,b,c;int tt = -1;
for(int i=0;i<m;i++){
scanf("%d%d%d",&a,&b,&c);
G[b].push_back(node(a,c));
if(a == 0){
tp[l++] = node(b,c);
}
}
int ans = dijstra_heap(n+1);
if(ans == INF){
//cout<<"bug"<<endl;
printf("-1\n");continue;
}
else{
int maxi = 0,maxx = INF;
for(int i=0;i<l;i++){
tp[i].len += dis[tp[i].v];
if(tp[i].len < maxx){
maxx = tp[i].len ;
maxi = tp[i].v;
}
}
for(int i=0;i<l;i++){
if(tp[i].len == maxx){
maxi = min(maxi,tp[i].v);
}
}
int flag = 0;
for(int i=0;i<l;i++){
if(tp[i].v == n+1 && tp[i].len == maxx){
printf("0\n"); flag = 1;break;
}
}
if(!flag)
printf("%d\n",maxi);
}
}
return 0;
}
D
占坑
E
水题。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#define mem(a,x) memset(a,x,sizeof(a))
using namespace std;
typedef long long ll;
const int N = 100010;int a[5];
char s[50];
int f[111];
int ans[111];
char G[111][111];
int main(){
int t;
scanf("%d",&t);
while(t--){
int n,m;scanf("%d%d",&n,&m);
mem(G,'.');
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++)
scanf(" %c",&G[i][j]);
}
int ans = 0;
for(int i=0;i<=n+1;i++){
for(int j=0;j<=m+1;j++){
if(G[i][j] =='.'){
int l = 0;
if(i-1>=0 && G[i-1][j] =='#') l++;
if(j-1>=0 && G[i][j-1] =='#') l++;
if(i<n+1 && G[i+1][j] =='#') l++;
if(j<m+1 && G[i][j+1] =='#') l++;
if(l == 1) ans++;
}
}
}
printf("%d\n",ans);
}
return 0;
}
F
占坑
G
规律题,用NIM的方法(3个数异或)打出表来发现了规律。
奇数都是0,偶数的话发现都是1,4,13,40,,3n+1. 转换成二进制后发现与二进制中1的个数有关。
2个1,是1,3个1是4,4个1是13.。。
f[n] = f[n-1]*3 + 1
f[n-1]*3 = f[n-2]*9 + 3
f[n] = f[n-2]*9 + (1+3)
f[n] = f[n-3]*27 + (1 + 3 + 9)
这样推下去,得出
f[n] = f[1] *(3^(n-1)) + (1-3^(n-1))/(1-3) 。。。 (用到了等比数列求和公式 Sn = a1(1-q^n))/(1-q))
化简一下 f[n] = (3^n - 1)/2 (这里的n是二进制中1的个数-1)
这里学到一个gcc编译器的内建函数,__builtin_popcount(x)
直接统计整数x转换成2进制中有多少1。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<queue>
#include<cstring>
#include<cmath>
#define mem(a,x) memset(a,x,sizeof(a))
#define INF 0x3f3f3f3f
using namespace std;
typedef long long ll;
const int MAXN = 2020;
int main(){
int T;scanf("%d",&T);
while(T--){
ll n;scanf("%lld",&n);
if(n < 6 || n&1) printf("0\n");
else{
int ans = __builtin_popcount(n);
if(ans <=1)printf("0\n");
else{
ans--;
printf("%lld\n",((ll)pow(3,ans)-1)/2);
}
//cout<<ans<<endl;
}
}
return 0;
}
H
//学习别人的做法,自己的找不出错了。。不过这个代码更省内存吧
#include<bits/stdc++.h>
using namespace std;
const int M =11111;
struct node{
int l,r;
}e[M];
int top;
char s[M];
char c[M][M/10];
char op[M];
int main(){
int T;scanf("%d",&T);
while(T--){
memset(s,0,sizeof(s));
int pos = 0, top = 0;
scanf("%s",op);
while(true){
scanf("%s",op);
int len = strlen(op);
int num = 0, i = 0;
for(i = 0;i < len ; i++){
if(op[i] != '[') c[top][i] = op[i];
else break;
}
c[top][i] = '\0';
for(i++;i<len;i++){
if(op[i] == ']') break;
num = num * 10 + op[i] - '0'; // 学习了
}
e[top].l = pos;
e[top].r = pos + num;
pos += num;
top++;
char ss = getchar();
if (ss == '\n') break;
}
while(1){
scanf("%s",op);
if(op[0] == 'r'){
scanf("%s",op); break;
}
else if(op[0] == 'c'){
scanf("%s",op);
for(int i = 0;i< top ;i++){
if(strcmp(op,c[i]) == 0){
for(int j=e[i].l;j<pos;j++){
if(s[j] == '\0') break;
printf("%c",s[j]);
}
printf("\n");
break;
}
}
}
else if(op[0] == 'g'){
scanf("%s",op);
for(int i = 0;i<top;i++){
if(strcmp(op,c[i]) == 0){
gets(op);
int len = strlen(op);
int k = 1,j;
for(j = e[i].l;j<e[i].r && k < len;j++, k++)
s[j] = op[k];
if(j < e[i].r)
s[j] = '\0';
break;
}
}
}
}
}
}
自己wa的代码,求指出啊~
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cstdlib>
#include <set>
#include <map>
using namespace std;
map<string,string> mp;
map<string,int>mp2;
map<string,int>mp3;
struct node{
string name;
int len;
int id;
};
int main(){
int T;scanf("%d",&T);
while(T--){
mp.clear(); mp2.clear(); mp3.clear();
getchar();
string a;
getline(cin,a);
int len = a.length();
node no[10100]; int cnt =0 ;
for(int i=0;i<len;i++){
if(a[i] == ' '){
string tmp = "";
int j = i+1;
for(;j<len;j++){
if(a[j] == '[') break;
}
tmp = a.substr(i+1,j-i-1);
no[cnt].name = tmp;
int k = j+1;
for(;k<len;k++)
if(a[k] == ']') break;
tmp = a.substr(j+1,k-j-1);
int tmpn = atoi(tmp.c_str());
no[cnt].len = tmpn;
no[cnt].id = cnt;
mp2[no[cnt].name] = cnt;
cnt++;
}
}
while(1){
string ord,num,str;
cin>>ord;
if(ord == "return"){
cin>>num; break;
}
else if (ord == "gets"){
cin>>num;
getchar();
getline(cin,str);
string tmp = str.substr(0,no[mp2[num]].len);
mp[num] = tmp;
if(str.length() >= no[mp2[num]].len)
mp3[num] = 1;
else
mp3[num] = 0;
}
else if(ord == "cout"){
cin>>num;
if(mp[num] == ""){
cout<<endl;
}
else{
cout<<mp[num];
if(mp3[num]){
int cc= mp2[num] + 1;
for(int i = cc; i < cnt;i++){
if(mp[no[i].name] == "") break;
cout<<mp[no[i].name] ;
if(!mp3[mp[no[i].name]])
{
continue;
}
else break;
}
}
cout<<endl;
}
}
}
}
}
I
占坑
J
阅读理解题,对于玩过炉石传说游戏的来说就是秒A了(果然ACMer要什么都懂。。)
#include<iostream>
#include<cstdio>
#include<cstring>
#define mem(a,x) memset(a,x,sizeof(a))
using namespace std;
typedef long long ll;
const int N = 100010;int a[5];
char s[50];
int main(){
int t;
scanf("%d",&t);
while(t--){
int n,hp; scanf("%d%d",&n,&hp);
getchar();
int C=0,M=0,O=0,B=0;
for(int i=0;i<n;i++){
gets(s);
if(s[0]=='C') C++;
if(s[0]=='M') M++;
if(s[0]=='O') O++;
if(s[0]=='B') B++;
}
int actO = O*(2+n-1+M*2);
int actB = B*(2+M*2);
if(actO + actB - hp >=0){
printf("Mrghllghghllghg!\n");
}
else
printf("Tell you a joke, the execution of Paladin.\n");
}
return 0;
}
K
字符串翻转,经典水题
#include<iostream>
#include<cstdio>
#include<cstring>
#define mem(a,x) memset(a,x,sizeof(a))
using namespace std;
typedef long long ll;
const int N = 100010;int a[5];
char s[10100];
int main(){
int t;
scanf("%d",&t);
getchar();
while(t--){
gets(s);
int len = strlen(s);
//cout<<s<<endl;
int l =0;
for(int i=0;i<=len;i++){
if(s[i] == ' ' || i == len){
for(int j=i-1;j>=l;j--) printf("%c",s[j]);
if(i != len)
printf(" ");
else
printf("\n");
l = i+1;
//cout<<" "<<i<<" "<<l<<endl;
}
}
}
return 0;
}