第五届合肥工业大学宣城校区程序设计大赛题解
问题 A: 小问题
时间限制: 1 Sec 内存限制: 128 MB Special Judge
题目描述
林喵喵特别喜欢解决女孩子们提出的问题.
输入
第一行T表示测试组数
第二行有一个数N, 表示集合A内元素的数量 Card(A) N≤20
第三行有N个集合A的元素,以空格分隔
第四行有一个A的元素p
输出
为了降低难度, 你只需要输出每个集合内数字的数量与总和, 总和小于231-1
每个输出的集合占用一行
每行两个数字, 第一个数表示非空集合元素的数量, 第二个数表示非空集合元素的总和
集合之间的顺序可随意调整
样例输入
样例输出
1 #include<bits/stdc++.h> 2 #define clr(x) memset(x,0,sizeof(0)) 3 #define clr_1(x) memset(x,-1,sizeof(x)) 4 #define LL long long 5 #define mod 1000000007 6 using namespace std; 7 const int N=1e2+10; 8 LL val[N]; 9 int T,n,m,h,p,ct,t; 10 LL sum; 11 int main() 12 { 13 scanf("%d",&T); 14 while(T--) 15 { 16 scanf("%d",&n); 17 for(int i=1;i<=n;i++) 18 scanf("%lld",&val[i]); 19 m=(1<<n)-1; 20 scanf("%d",&p); 21 for(int i=1;i<=n;i++) 22 if(p==val[i]) 23 { 24 p=i; 25 break; 26 } 27 for(int i=1;i<=m;i++) 28 if(((i>>(p-1))&1)==0) 29 { 30 ct=0; 31 t=0; 32 sum=0; 33 h=i; 34 while(h) 35 { 36 t++; 37 if(h&1) 38 { 39 sum+=val[t]; 40 ct++; 41 } 42 h>>=1; 43 } 44 printf("%d %lld\n",ct,sum); 45 } 46 } 47 return 0; 48 } 49
问题 B: 统计词频
时间限制: 1 Sec 内存限制: 128 MB提交: 359 解决: 22
题目描述
给出一段英文文字, 统计每个单词出现的次数(忽略大小写)
单词字母范围为( a~z 或 A~Z ),没有奇怪的字符
输入
第一行组数T
第二行单词数N (N<=10000)
后面N行有N个非空的单词
输出
输出小写单词和数量,单词按照字典序排序输出
一个单词占一行
样例输入
样例输出
1 #include<bits/stdc++.h> 2 #define clr(x) memset(x,0,sizeof(0)) 3 #define clr_1(x) memset(x,-1,sizeof(x)) 4 #define LL long long 5 #define mod 1000000007 6 using namespace std; 7 const int N=1e5+10; 8 int T,n,m,h,p,ct,t; 9 string s; 10 map<string,LL>::iterator it; 11 int main() 12 { 13 scanf("%d",&T); 14 while(T--) 15 { 16 scanf("%d",&n); 17 map<string,LL> num; 18 for(int i=1;i<=n;i++) 19 { 20 cin>>s; 21 for(int j=0;j<s.size();j++) 22 s[j]=tolower(s[j]); 23 num[s]++; 24 } 25 for(it=num.begin();it!=num.end();it++) 26 printf("%s %lld\n",(it->first).c_str(),it->second); 27 } 28 return 0; 29 }
问题 C: 机房问题
时间限制: 2 Sec 内存限制: 128 MB提交: 214 解决: 18
题目描述
在你们写题的时候,萌萌的林喵喵同学其实在暗中观察你们(Big Miao is watching you!)
其中观察的一项就是要统计出一段时间内哪个时刻上机人数最多。
你能否比林喵喵更快地统计出来呢?
输入
T表示组数
N表示数据数量
接下来N行每行三个整数t1,t2,n
表示n个学生在t1到t2使用了机房电脑(包含t1,t2)
0<t1<t2<=10000000
0<n<=10000000
输出
输出一个时间t, 这个时刻上机人数最多
若有多个最大值则输出最小的t
样例输入
样例输出
1 #include<bits/stdc++.h> 2 #define clr(x) memset(x,0,sizeof(0)) 3 #define clr_1(x) memset(x,-1,sizeof(x)) 4 #define LL long long 5 #define mod 1000000007 6 using namespace std; 7 const int N=1e5+10; 8 int T,n,h,p,ct; 9 LL t1,t2,m,sum,maxn,pt; 10 string s; 11 map<LL,LL>::iterator it; 12 int main() 13 { 14 scanf("%d",&T); 15 while(T--) 16 { 17 scanf("%d",&n); 18 map<LL,LL> num; 19 for(int i=1;i<=n;i++) 20 { 21 scanf("%lld%lld%lld",&t1,&t2,&m); 22 num[t1]+=m; 23 num[t2+1]-=m; 24 } 25 num[0]=0; 26 maxn=0; 27 pt=0; 28 sum=0; 29 for(it=num.begin();it!=num.end();it++) 30 { 31 sum+=it->second; 32 if(sum>maxn) 33 { 34 maxn=sum; 35 pt=it->first; 36 } 37 } 38 printf("%lld\n",pt); 39 } 40 return 0; 41 }
问题 D: 帅宝宝的xor
时间限制: 2 Sec 内存限制: 128 MB提交: 43 解决: 10
题目描述
输入
输出
样例输入
样例输出
01型字典树模板题。
写过字典树的应该都会,稍难题。
1 #include<bits/stdc++.h> 2 #define clr(x) memset(x,0,sizeof(x)) 3 #define clr_1(x) memset(x,-1,sizeof(x)) 4 #define LL long long 5 #define mod 1000000007 6 using namespace std; 7 const int N=1e5+10; 8 struct Node 9 { 10 int next[2]; 11 }; 12 struct Trie 13 { 14 Node node[N*33]; 15 int cnt; 16 void init() 17 { 18 cnt=0; 19 clr_1(node); 20 } 21 void add(LL x) 22 { 23 int t,u=0; 24 for(int i=31;i>=0;i--) 25 { 26 t=(x>>i)&1; 27 if(node[u].next[t]==-1) 28 { 29 node[u].next[t]=++cnt; 30 } 31 u=node[u].next[t]; 32 } 33 return ; 34 } 35 LL query(LL x) 36 { 37 int t,u=0; 38 LL ans=0; 39 for(int i=31;i>=0;i--) 40 { 41 t=(x>>i)&1; 42 ans<<=1; 43 if(node[u].next[t^1]==-1) 44 { 45 ans|=t; 46 u=node[u].next[t]; 47 } 48 else 49 { 50 ans|=(t^1); 51 u=node[u].next[(t^1)]; 52 } 53 } 54 return ans; 55 } 56 }trie; 57 int n,m,k,t,q; 58 int main() 59 { 60 while(scanf("%d",&n)!=EOF) 61 { 62 trie.init(); 63 for(int i=1;i<=n;i++) 64 { 65 scanf("%d",&k); 66 trie.add((LL)k); 67 } 68 scanf("%d",&q); 69 for(int i=1;i<=q;i++) 70 { 71 scanf("%d%d",&t,&k); 72 if(t==1) 73 trie.add((LL)k); 74 else 75 printf("%lld\n",trie.query((LL)k)); 76 } 77 printf("\n"); 78 } 79 return 0; 80 }
问题 E: N马问题
时间限制: 2 Sec 内存限制: 128 MB提交: 23 解决: 4
题目描述
输入
多组数据,请使用读取多组数据的写法
接下来有若干行,每组数据有一行,m和n,表示棋盘是m行n列的,1<=n,m<=1000
输出
输出一个数字,表示m*n棋盘最多摆放马的数量
样例输入
样例输出
1 #include <iostream> 2 #include <cstdio> 3 using namespace std; 4 5 int solve(int n, int m) { 6 if (n < m) return solve(m, n); 7 else if (m==1) return n; 8 else if (m==2) { 9 return (n/4)*4+((n%4>1)?2:n%4)*2; 10 } 11 else return (n*m+1)/2; 12 } 13 14 int main() { 15 16 int r,c; 17 while (scanf("%d%d", &r, &c)!=EOF) { 18 printf("%d\n", solve(r, c)); 19 } 20 return 0; 21 }
问题 F: xor game
时间限制: 1 Sec 内存限制: 128 MB提交: 26 解决: 7
题目描述
输入
输出
若帅宝宝获胜输出"shuaibaobao"否则输出"linmiaomiao"。
样例输入
样例输出
提示
xor自反性,b^a^b=a。
cf上的题,稍难的思维题吧。(毕竟已经写了提示了)。
只不过我把范围改大了,防止你们瞎暴力23333。
首先两个数列内的数都完全不相同。那么任意两个数异或的结果数列内最多只有一个数是对应的。
然后考虑异或的自反性。
如果我们xi^yj==ci(c表示x、y中任意一个数列),那么肯定有xi^ci==yj或者yj^ci==xi。这取决于c是哪个数列。
因此这样的数对是成对出现的,有偶数个。linmiaomiao一定赢。
1 #include<bits/stdc++.h> 2 #define clr(x) memset(x,0,sizeof(x)) 3 #define clr_1(x) memset(x,-1,sizeof(x)) 4 #define LL long long 5 #define mod 1000000007 6 using namespace std; 7 const int N=1e5+10; 8 int n,m,k,t,q,T; 9 LL x[N],y[N]; 10 int main() 11 { 12 // freopen("10.in","r",stdin); 13 // freopen("10.out","w",stdout); 14 scanf("%d",&T); 15 while(T--) 16 { 17 scanf("%d",&n); 18 for(int i=1;i<=n;i++) 19 scanf("%lld",&x[i]); 20 for(int i=1;i<=n;i++) 21 scanf("%lld",&y[i]); 22 printf("linmiaomiao\n"); 23 } 24 return 0; 25 } 26
问题G: 旺财的集邮策略
时间限制: 2 Sec 内存限制: 128 MB提交: 53 解决: 3
题目描述
输入
输出
一个整数,表示在不超过K张邮票的情况下从1分开始能够最大连续可贴出的邮资是多少。
样例输入
样例输出
1 //wanghan's code 2 #include "iostream" 3 #include "cstdio" 4 #include "cstring" 5 #include "string" 6 using namespace std; 7 const int maxn=2e6+100; 8 const int INF=1<<30; 9 int K,n; 10 int dp[maxn],v[100]; 11 int main() 12 { 13 cin>>K>>n; 14 int ans=0; 15 for(int i=1;i<=n;i++){ 16 cin>>v[i]; 17 ans=max(ans,v[i]); 18 } 19 int m=2e6; 20 for(int i=1;i<=m;i++) 21 dp[i]=INF; 22 for(int i=1;i<=n;i++){ 23 for(int j=v[i];j<=m;j++){ 24 dp[j]=min(dp[j],dp[j-v[i]]+1); 25 } 26 } 27 int res=1; 28 for(int i=1;i<=m;i++){ 29 if(dp[i]>K){ 30 res=i; break; 31 } 32 } 33 cout<<res-1<<endl; 34 }
问题 H: 网络收费
时间限制: 1 Sec 内存限制: 64 MB提交: 30 解决: 3
题目描述
输入
输出
你的程序只需要向输出文件输出一个整数,表示支付给网络公司的最小总费用。(单位:元)
样例输入
样例输出
noi2006的原题,某位陈瑜希的论文题。详见我树形dp系列题解。
1 #include<bits/stdc++.h> 2 #define clr(x) memset(x,0,sizeof(x)) 3 #define clr_1(x) memset(x,-1,sizeof(x)) 4 #define clrmax(x) memset(x,0x3f3f3f3f,sizeof(x)) 5 #define mod 1000000007 6 #define LL long long 7 using namespace std; 8 const int maxN=5e3+10; 9 int f[maxN][maxN]; 10 int flow[maxN][maxN]; 11 int c[maxN]; 12 int cost[maxN][20],fa[maxN][20]; 13 bool chose[maxN]; 14 int N,n,m,k,ans,p; 15 int dfs(int u,int dep,int sta)//sta前从右往左第dep+1位开始是该结点分配的B方式的数量,1~dep位为其祖先结点na和nb的大小相对关系,表现为B收费为1,A收费为0。 16 { 17 if(f[u][sta]!=0x3f3f3f3f) return f[u][sta]; 18 int num=sta>>dep; 19 int fasta=sta^(num<<dep); 20 //该结点的收费选择chos 21 int chos=(1<<(N-dep))-num>=num?1:0; 22 //叶子结点处理返回 23 if(dep==N) 24 { 25 int v=u-(n-1); 26 fasta<<=1; 27 fasta|=chos; 28 if(num^chose[v]) 29 f[u][sta]=c[v]; 30 else 31 f[u][sta]=0; 32 for(int i=N;i>=0;i--) 33 { 34 if(!((fasta&1)^num)) 35 f[u][sta]+=cost[v][i]; 36 fasta>>=1; 37 } 38 return f[u][sta]; 39 } 40 //约束左右结点取B的数量在合理范围内,并选择其中最小的一个和。 41 int minx=max(0,num-(1<<N-dep-1)); 42 int maxx=min(num,1<<N-dep-1); 43 for(int i=minx;i<=maxx;i++) 44 f[u][sta]=min(dfs(u<<1,dep+1,(i<<dep+1)|(fasta<<1|chos))+dfs(u<<1|1,dep+1,(num-i<<dep+1)|(fasta<<1|chos)),f[u][sta]); 45 return f[u][sta]; 46 } 47 int main() 48 { 49 scanf("%d",&N); 50 n=1<<N; 51 for(int i=1;i<=n;i++) 52 { 53 scanf("%d",&p); 54 chose[i]=p; 55 } 56 for(int i=1;i<=n;i++) 57 scanf("%d",&c[i]); 58 for(int i=1;i<=n;i++) 59 for(int j=i+1;j<=n;j++) 60 scanf("%d",&flow[i][j]); 61 //计算子结点i(树上编号为i+n-1)在深度为j的祖先 62 for(int i=1;i<=n;i++) 63 { 64 k=i+n-1; 65 for(int j=N;j>=0;j--) 66 { 67 fa[i][j]=k; 68 k>>=1; 69 } 70 } 71 clr(cost); 72 //若i,j在深度为k处祖先相同,那末将流量费用flow[i,j]加到i和j在深度k所需要的费用中。 73 for(int i=1;i<=n;i++) 74 for(int j=i+1;j<=n;j++) 75 for(int k=N;k>=0;k--) 76 if(fa[i][k]==fa[j][k]) 77 { 78 cost[i][k]+=flow[i][j]; 79 cost[j][k]+=flow[i][j]; 80 break; 81 } 82 clrmax(f); 83 ans=0x3f3f3f3f; 84 for(int i=0;i<=n;i++) 85 ans=min(ans,k=dfs(1,0,i)); 86 printf("%d\n",ans); 87 return 0; 88 }
问题 I: 签到题
时间限制: 5 Sec 内存限制: 16 MB提交: 241 解决: 18
题目描述
输入
多组数据,数据不超过1000000组。对于每组数据包含一个整数,代表冬学姐的仰慕者所在城市个数n(0≤n≤1018)。
输出
对于每组数据,输出它的数据编号(从1开始),以及冬学姐最少需要的费用。
样例输入
样例输出
来源
1 #include<bits/stdc++.h> 2 #define clr(x) memset(x,0,sizeof(x)) 3 #define clr_1(x) memset(x,-1,sizeof(x)) 4 #define LL long long 5 #define mod 1000000007 6 using namespace std; 7 int main() 8 { 9 int kase=0; 10 LL n; 11 while(scanf("%lld",&n)!=EOF) 12 printf("Case %d: %lld\n",++kase,n>>1); 13 return 0; 14 }
问题 J: 水题
时间限制: 1 Sec 内存限制: 128 MB提交: 11 解决: 2
题目描述
输入
多组数据,数据不超过10000组。每组数据包含一个整数n,代表有向图结点个数(2≤n≤1018)。
输出
对于每组数据,输出它的最大流 mod 109+7后的答案。
样例输入
样例输出
1 #include<bits/stdc++.h> 2 #define clr(x) memset(x,0,sizeof(x)) 3 #define LL long long 4 #define mod 1000000007 5 using namespace std; 6 LL quick_pow(LL x, LL n) { 7 LL res = 1; 8 x=(x%mod+mod)%mod; 9 while(n) { 10 if(n&1) 11 res=res*x% mod; 12 n >>=1; 13 x =x*x% mod; 14 } 15 return res; 16 } 17 int main() 18 { 19 LL n,m,q,l,ans,k,kk; 20 int t; 21 while(scanf("%lld",&n)!=EOF) 22 { 23 t=0; 24 n--; 25 m=n; 26 while(m) 27 { 28 t++; 29 m>>=1; 30 } 31 q=1; 32 m=(q<<(t-1)); 33 ans=(m%mod)*((1+m)%mod)%mod; 34 ans=ans*quick_pow(2,mod-2)%mod; 35 n-=m; 36 kk=1; 37 k=2; 38 while(k<=n+kk) 39 { 40 ans=(ans%mod+(((n+kk)/k)%mod)*((kk%mod)*(kk%mod)%mod+1)%mod)%mod; 41 if(k==LLONG_MAX) 42 break; 43 kk=k; 44 k<<=1; 45 } 46 printf("%lld\n",ans); 47 } 48 return 0; 49 }
问题 K: 临界区资源问题
时间限制: 1 Sec 内存限制: 128 MB提交: 404 解决: 53
题目描述
输入
输出
输出一行,按上升顺序输出无效指令编号。
样例输入
样例输出
真签到题,比以上水题还水。
就是题目很忽悠23333,然而这是连两个for都能过的题。当初预期是所有写题的人都能过。
然而还是有人纠结前面问题而没看后面问题。导致过题人数只有一半。
1 #include<bits/stdc++.h> 2 #define clr(x) memset(x,0,sizeof(x)) 3 #define clr_1(x) memset(x,-1,sizeof(x)) 4 #define LL long long 5 #define mod 1000000007 6 using namespace std; 7 const int N=1e2+10; 8 int n,m; 9 int a[N],b[N]; 10 int main() 11 { 12 scanf("%d%d",&n,&m); 13 clr(b); 14 for(int i=1;i<=m;i++) 15 { 16 scanf("%d",&a[i]); 17 if(b[a[i]]) 18 { 19 printf("%d ",i); 20 } 21 else 22 { 23 b[a[i]]=1; 24 } 25 } 26 printf("\n"); 27 return 0; 28 }