【前言】
周六第一天跑到实验室复习。
复习到一半看到有个contest。看了一题,觉得可以做,然后就YY了。
然后一发就不可收拾了……
确实是好久没做ACM了,最近都忙着大作业。
【题解】
首先看到第三题。由于那些题目是hdu没有的,所以只能把题目也copy过来了。
由于每个数都很小,所以开个数组存一下就可以了。
于是就把水题敲出来了。看来我水题帝的称号还是名副其实的啊。
小强与那个她的故事
Time Limit : 3000/1000ms (Java/Other) Memory Limit : 65535/32768K (Java/Other)
Total Submission(s) : 16 Accepted Submission(s) : 9
Font: Times New Roman | Verdana | Georgia
Font Size: ← →
Problem Description
USTC一年一度的“美丽邂逅”都异常火爆,特别是今年传说中千年难遇的“千年光棍节”,当然这一活动,传说中的小强肯定要去凑热闹,“众里寻他千百度,蓦然回首,那人却在灯火阑珊处”,小强终于遇到了传说中的那个她,于是速度上前搭讪,可是那个她在小强还未来得及开口之前,就一眼认出了小强(有可能是因为长得太帅了吧) 。于是那个她竟然公开撒起了娇,“小强哥哥,找你找得好苦呀,我们算法课老师给了一个题,不会呀,我问了好多人,都不会,如果小强哥哥会的话。。。我。。。”。 小强听到这些话,顿时春心荡漾起来,不过他故作平静,很Man地说了句“说!”。于是那个她说出了困扰她很久的问题。
有N个正整数,求出他们两两之差的绝对值之和。比如有如下4个数:
4 3 5 2,那么答案为:
|4-3|+|4-5|+|4-2|+|3-5|+|3-2|+|5-2|=10
这对小强来说,简直就是“一块蛋糕”。但是小强还有其他妹子要邂逅,所以将这个问题留给你来搞定了。
有N个正整数,求出他们两两之差的绝对值之和。比如有如下4个数:
4 3 5 2,那么答案为:
|4-3|+|4-5|+|4-2|+|3-5|+|3-2|+|5-2|=10
这对小强来说,简直就是“一块蛋糕”。但是小强还有其他妹子要邂逅,所以将这个问题留给你来搞定了。
Input
第一行输入一个正整数T(T<=100),代表下面共有T组测试数据。每组测试数据包括两部分:
首先一个正整数N(1<=N<=100000),代表下面有N个正整数。
接下来输入N个正整数,每个正整数不大于200。
首先一个正整数N(1<=N<=100000),代表下面有N个正整数。
接下来输入N个正整数,每个正整数不大于200。
Output
输出相应的答案,答案可能会超过int范围,但是保证不会超过long long范围。
Sample Input
1 4 4 3 5 2
Sample Output
10
Author
【1003代码】
#include <iostream>
using namespace std;
#define LL __int64
int num[205];
int main()
{
int t;
int n, x, i, j;
LL sum;
scanf("%d", &t);
while(t--)
{
scanf("%d", &n);
memset(num, 0, sizeof(num));
sum = 0;
for (i=0; i<n; i++)
{
scanf("%d", &x);
num[x]++;
}
for (i=1; i<=200; i++)
{
if (num[i]!=0)
{
for (j=i+1; j<=200; j++)
{
if (num[j]!=0)
{
sum += (LL)(j-i)*num[i]*num[j];
}
}
}
}
printf("%I64d\n", sum);
}
return 0;
}
然后发现1007是a+b问题,哎,直接copy代码。
然后看到第二题。
生成函数之类的东东吧。自己功力不深,还没办法应用。
于是随便想。由于是等号。所以枚举5z,对于n-5z算出可以得到多少个2y,剩下的就是x了。
O(n)的复杂度就可以出解。后来发现确实是可以用生产函数来做,思路也是差不多这样,不过可能就显得更严谨一些。
W和方程的故事
Time Limit : 3000/1000ms (Java/Other) Memory Limit : 65535/32768K (Java/Other)
Total Submission(s) : 3 Accepted Submission(s) : 2
Font: Times New Roman | Verdana | Georgia
Font Size: ← →
Problem Description
W最近在研究一个方程X+2Y+5Z=N,其中X,Y,Z是未知数,N是一个已知的整数且X,Y,Z,N都是非负整数。他想求出该方程共有多少组解,你能帮助他吗?
Input
第一行输入一个正整数T(T<=100),代表下面共有T组测试数据。下面T行,每行一个整数N(0<=N<=1000000)。
Output
输出该方程解的组数。
Sample Input
2 0 6
Sample Output
1 5
Author
【1002代码】
#include <iostream>
using namespace std;
int main()
{
int i;
int n, t;
__int64 ct;
scanf("%d", &t);
while(t--)
{
scanf("%d", &n);
ct = 0;
for (i=0; i*5<=n; i++)
{
ct += (__int64)(n-i*5)/2+1;
}
printf("%I64d\n", ct);
}
return 0;
}
之后就打算继续去复习了。但是受不了ACM的诱惑,于是又回来做了。
这道题由于所给数的范围比较小,所以2^20内就可以解决。所以可以先打表。
异样的二进制
Time Limit : 3000/1000ms (Java/Other) Memory Limit : 65535/32768K (Java/Other)
Total Submission(s) : 6 Accepted Submission(s) : 3
Font: Times New Roman | Verdana | Georgia
Font Size: ← →
Problem Description
话说LMM是USTC_ACM集训队为数不多的MM之一,当然每天慕名前来ym的人都很多,在风和日丽的今天,又来了三位。第一位是号称WA神的WA神,WA神是出了名的数学帝,送给了LMM一本微积分习题集,“oh,my god”,讨厌微积分的LMM果断木有给他ym的机会。第二位是号称物理帝的CBX大神,他同样也木有得到ym的机会,因为他竟然送了一本量子力学+量子化学的综合参考书给LMM,话说LMM讨厌死那些东西了。
第三位是号称WSN(Wo Shen Niu)的WSN帝,别看他名字很WS,可竟然获得了近距离ym LMM的机会,为什么呢? 很简单,因为他是“程序猿”。^-^
因为他知道LMM是CS专业的,对二进制转换非常熟悉,例如13的二进制为1101,因为13=1*2^3+1*2^2+0*2^1+1*2^0,所以他想证明他的魅力,带来了所谓的“负二进制”问题,将基数改为了-2,例如1101,实际上代表着:1*(-2)^3+1*(-2)^2+0*(-2)^2+1*(-2)^0=-3,所以-3的“负二进制”为1101.
同样作为“程序猿”的你,会这个问题么?如果会的说,说不定还能获得ym LMM的机会额,亲。
话说在科大要ym到一个妹纸,比进Final都还难呀。。。
第三位是号称WSN(Wo Shen Niu)的WSN帝,别看他名字很WS,可竟然获得了近距离ym LMM的机会,为什么呢? 很简单,因为他是“程序猿”。^-^
因为他知道LMM是CS专业的,对二进制转换非常熟悉,例如13的二进制为1101,因为13=1*2^3+1*2^2+0*2^1+1*2^0,所以他想证明他的魅力,带来了所谓的“负二进制”问题,将基数改为了-2,例如1101,实际上代表着:1*(-2)^3+1*(-2)^2+0*(-2)^2+1*(-2)^0=-3,所以-3的“负二进制”为1101.
同样作为“程序猿”的你,会这个问题么?如果会的说,说不定还能获得ym LMM的机会额,亲。
话说在科大要ym到一个妹纸,比进Final都还难呀。。。
Input
多组测试数据,每组输入一个数N(-100000<=N<=100000),代表着要转换的数。
Output
输出相应的转换结果。
Sample Input
-3 11
Sample Output
1101 11111
Author
【1004代码】
#include <iostream>
using namespace std;
const int maxn = 100000;
struct node
{
int len;
bool by[30];
}num[2*maxn+5];
int value[30];
void dfs(int v, int m, node now, int cur)
{
if (v==m)
{
if (cur<=maxn && cur>=-maxn && num[cur+maxn].len==0)
memcpy(&num[cur+maxn], &now, sizeof(node));
return;
}
now.len++;
now.by[now.len-1] = false;
dfs(v+1, m, now, cur);
now.by[now.len-1] = true;
cur += value[v];
dfs(v+1, m, now, cur);
}
void show(int n)
{
n += maxn;
int i;
for (i=num[n].len-1; i>=0; i--)
{
if (num[n].by[i]) break;
}
if (i<0) i=0;
for ( ; i>=0; i--)
{
if (num[n].by[i]) printf("1");
else printf("0");
}
printf("\n");
}
int main()
{
int i;
value[0] = 1;
for (i=1; i<20; i++) value[i] = value[i-1]*(-2);
for (i=-maxn; i<=maxn; i++) num[i+maxn].len = 0;
node now;
now.len = 0;
dfs(0, 20, now, 0);
int n;
while(scanf("%d", &n)!=EOF)
{
show(n);
}
return 0;
}
看到1008有人很快出了,于是断定为规律题。开始找规律。
然后果真被我找到了。A掉。
三角形
Time Limit : 2000/1000ms (Java/Other) Memory Limit : 65536/32768K (Java/Other)
Total Submission(s) : 6 Accepted Submission(s) : 3
Font: Times New Roman | Verdana | Georgia
Font Size: ← →
Problem Description
用N个三角形最多可以把平面分成几个区域?
Input
输入数据的第一行是一个正整数T(1<=T<=10000),表示测试数据的数量.然后是T组测试数据,每组测试数据只包含一个正整数N(1<=N<=10000).
Output
对于每组测试数据,请输出题目中要求的结果.
Sample Input
2 1 2
Sample Output
2 8
Author
【1008代码】
#include <iostream>
using namespace std;
const int maxn = 10000;
int x[maxn+5];
int main()
{
int i;
x[1] = 2;
for (i=2; i<=maxn; i++) x[i] = x[i-1] + 6*(i-1);
int t, n;
scanf("%d", &t);
while(t--)
{
scanf("%d", &n);
printf("%d\n", x[n]);
}
return 0;
}
然后决定动手虎视眈眈已久的1009。
只是一道简单的字典树,不过就是有点懒得打。
没想到居然8分钟就被我敲出来了。看来还是有点实力的。
统计难题
Time Limit : 4000/2000ms (Java/Other) Memory Limit : 131070/65535K (Java/Other)
Total Submission(s) : 3 Accepted Submission(s) : 2
Font: Times New Roman | Verdana | Georgia
Font Size: ← →
Problem Description
Ignatius最近遇到一个难题,老师交给他很多单词(只有小写字母组成,不会有重复的单词出现),现在老师要他统计出以某个字符串为前缀的单词数量(单词本身也是自己的前缀).
Input
输入数据的第一部分是一张单词表,每行一个单词,单词的长度不超过10,它们代表的是老师交给Ignatius统计的单词,一个空行代表单词表的结束.第二部分是一连串的提问,每行一个提问,每个提问都是一个字符串.
注意:本题只有一组测试数据,处理到文件结束.
注意:本题只有一组测试数据,处理到文件结束.
Output
对于每个提问,给出以该字符串为前缀的单词的数量.
Sample Input
banana band bee absolute acm ba b band abc
Sample Output
2 3 1 0
Author
【1009代码】
#include <iostream>
using namespace std;
struct node
{
int ct;
int next[26];
}tree[400000];
int tct;
int root;
int new_node()
{
memset(&tree[tct], 0, sizeof(node));
return tct++;
}
void insert(char *s)
{
int rt = root;
int i = 0;
while(s[i]!='\0')
{
tree[rt].ct++;
int tmp = s[i]-'a';
if (tree[rt].next[tmp]==0)
tree[rt].next[tmp] = new_node();
rt = tree[rt].next[tmp];
i++;
}
tree[rt].ct++;
}
int solve(char *s)
{
int rt = root;
int i = 0;
while(s[i]!='\0')
{
int tmp = s[i]-'a';
if (tree[rt].next[tmp]==0) return 0;
rt = tree[rt].next[tmp];
i++;
}
return tree[rt].ct;
}
int main()
{
char str[20];
tct = 0;
root = new_node();
while(gets(str))
{
if (str[0]=='\0') break;
insert(str);
}
while(gets(str))
{
printf("%d\n", solve(str));
}
return 0;
}
最后剩下三道题没做。
第一题好像是线段树,前阵子看过,不过还没学到。
序列操作
Time Limit : 3000/1000ms (Java/Other) Memory Limit : 65535/32768K (Java/Other)
Total Submission(s) : 0 Accepted Submission(s) : 0
Font: Times New Roman | Verdana | Georgia
Font Size: ← →
Problem Description
给你一个由N个正整数组成的序列,现在你可以对该序列进行如下两种操作:
Q L R:输出区间[L,R](1<=L,R<=N)中最长连续不下降子序列的长度。
C L R P:将区间[L,R] (1<=L,R<=N)中的每个整数都替换成整数P。
作为USTC的程序精英们,你能很顺利的解决这个问题么?
Q L R:输出区间[L,R](1<=L,R<=N)中最长连续不下降子序列的长度。
C L R P:将区间[L,R] (1<=L,R<=N)中的每个整数都替换成整数P。
作为USTC的程序精英们,你能很顺利的解决这个问题么?
Input
第一行输入一个正整数T,代表下面有T组测试数据(T<=10)。
针对每组测试数据:
首先输入两个正整数N Q(1<=N<=100000,1<=Q<=100000),分别代表序列的长度和操作的次数。
接着输入N个正整数(每个正整数不大于1000)。
最后输入Q行,代表有Q次操作,每行有两种可能的形式:Q L R 或
C L R P。意义如上所示,其中P不大于1000。
注意: L有可能会大于R。
针对每组测试数据:
首先输入两个正整数N Q(1<=N<=100000,1<=Q<=100000),分别代表序列的长度和操作的次数。
接着输入N个正整数(每个正整数不大于1000)。
最后输入Q行,代表有Q次操作,每行有两种可能的形式:Q L R 或
C L R P。意义如上所示,其中P不大于1000。
注意: L有可能会大于R。
Output
针对每次Q L R操作,输出对应区间[L,R]中最长连续不下降子序列的长度。
Sample Input
1 6 5 1 2 3 4 5 6 Q 1 6 C 4 3 2 Q 1 3 C 4 5 3 Q 2 5
Sample Output
6 3 4