和谐
harmony.pas/c/cpp
【问题描述】
小k同学本来想给这个题套一个很好玩的背景的,但是因为一些原因(看题目名,你们懂的),这题的题面就变得非常无聊了。
对于任意四个两两不同的数,记
,考虑以下6个值:
,在这6个值中sum的约数个数记为这四个数的和谐度。例如0,7,2,3这4个数的和谐度为2.因为0+2和0+3是这4个数的和12的约数。
现在小k想知道两个问题:1. 如果他任意写下4个数,和谐度最大可能是多少;2. 满足并且A、B、C、D这4个数的和谐度为第1问中的值的所有四元组
一共有多少组。
【输入格式】
输入一行2个整数L和R,意义如上所述。
【输出格式】
输出2行,每行一个整数,分别表示2问的答案。
【样例输入】
harmony.in
1 30
【样例输出】
harmony.out
4
3
【样例解释】
和谐度最大只能达到4,没有和谐度超过4的4个数
在[1, 30]中,满足和谐度为4的4个数共有3组:
1. 1 5 7 11
2. 2 10 14 22
3. 1 11 19 29
【数据规模和约定】
分解因式
factorize.pas/c/cpp
【问题描述】
众所周知,整系数范围内分解因式是一个非常难的问题。为了解决这个问题,人们想出了各种公式和方法,例如平方差公式、立方差公式、立方和公式、提取公因式、十字相乘法等等。现在“伟大”的只会空想的不切实际的伪数学爱好者小k同学希望能借助计算机解决这个问题。
为了让自己的题目显得不那么丧心病狂一点,小k同学决定只要你解决一类特殊的因式分解问题,那就是分解. 在整系数范围内分解到不能继续分解为止。换句话说,最后的答案中每个因式不含更低次数的因式。
不过小k后来意识到这个问题还是很丧心病狂,为了降低题目难度,小k给出一个提示:一个多项式是另一个多项式
的因式当且仅当a是b的一个约数。
【输入格式】
【输出格式】
输出一行一个字符串,表示因式分解的结果。最后的输出中每个因式应该不含空格,系数为1或-1时应省略1,系数为0的项应该省略,每个因式应该降幂排列,并且保证首项系数为正。除此以外,我们要求按如下顺序排列因式:优先输出次数低的因式,对于次数相同的因式,依次比较每个因式的系数,从高指数项到低指数项,且包括被省略即系数为0的项。系数首先比较绝对值,其次比较符号。绝对值小的系数字典序序小,绝对值相同时比较符号,负号字典序比正号小。字典序越小的因式应该排在越前面输出。
【样例输入】
factorize.in
20
【样例输出】
factorize.out
(x - 1) (x + 1) (x^2 + 1) (x^4 – x^3 + x^2 - x + 1) (x^4 + x^3 + x^2 + x + 1) (x^8 – x^6 + x^4 – x^2 + 1)
【数据规模和约定】
投票
vote.pas/c/cpp
【问题描述】
小k同学正在玩一个游戏,在游戏中他扮演了一个马戏团的老板,现在小k同学需要利用马戏团中的A只猫和B只狗举办一次表演,表演之前他让观众进行了投票,投票的类容是:我想看到第___号猫/狗的表演,不想看到第___号猫/狗的表演。注意到每个观众都是更喜欢猫或更喜欢狗,所以两个空后面一定会被勾上不同的内容。喜欢猫的观众会在第一空后面选择猫,第二空后面选择狗;反之就会在第一空后面选择狗,第二空后面选择猫。对于每一个观众,只有当TA投票的内容都被满足了(即TA想看到的动物出场表演,TA不想看到的动物不参与表演)的时候,TA才会来看表演。当然啦,看表演是要付门票钱的,作为马戏团的老板,小k自然是希望来的人越多越好了。他想找到一个安排动物表演的方案,使得来看表演的观众尽量多。
【输入格式】
第1行3个正整数n、m、k,分别表示猫、狗和观众的数量
第2~k+1行,每行描述了一个观众的投票内容。
首先输入一个字符C或D紧接着是一个数字,表示某个观众想看到的动物,然后是一个空格隔开,接下去又是一个C或D加上一个数字,表示这个观众不想看到的动物,同一行中一定不会出现两个C或两个D。
【输出格式】
输出一行一个正整数,表示小k在最优的安排下可以吸引多少观众来看表演。
【样例输入】
vote.in
1 2 4
C1 D1
C1 D1
C1 D2
D2 C1
【样例输出】
vote.out
3
【数据规模和约定】
#include <cstdio> #include <algorithm> using namespace std; int n,m,k; int love[1000][2],hate[1000][2]; int map[1000][1000]; int id[1000]; bool v[1000]; bool use[1000]; int match[1000]; int ans; bool dfs(int x){ for (int i=1;i<=map[x][0];i++){ if (!use[map[x][i]]){ use[map[x][i]]=true; if (match[map[x][i]]==0 || dfs(match[map[x][i]])){ match[map[x][i]]=x; return true; } } } return false; } int main(){ freopen("vote.in","r",stdin); freopen("vote.out","w",stdout); scanf("%d%d%d\n",&n,&m,&k); n=m=0; for (int i=1;i<=k;i++){ char c1,c2; int t1,t2; scanf("%c%d %c%d\n",&c1,&t1,&c2,&t2); if (c1=='C'){ love[++n][0]=t1; hate[n][0]=t2; }else{ love[++m][1]=t1; hate[m][1]=t2; } } for (int i=1;i<=n;i++){ for (int j=1;j<=m;j++){ if (love[i][0]==hate[j][1] || hate[i][0]==love[j][1]) map[i][++map[i][0]]=j; } } int ans=0; for (int i=1;i<=n;i++){ memset(use,0,sizeof(use)); if (dfs(i)) ans++; } printf("%d\n",k-ans); return 0; }
树形图计数
count.pas/c/cpp
【问题描述】
小k同学最近正在研究最小树形图问题。所谓树形图,是指有向图的一棵有根的生成树,其中树的每一条边的指向恰好都是从根指向叶结点的方向。现在小k在纸上画了一个图,他想让你帮忙数一下这个图有多少棵树形图。
【输入格式】
第1行输入1个正整数:n,表示图中点的个数
第2~n+1行每行输入n个字符,描述了这个图的邻接矩阵。第i+1行第j个字符如果是0则表示没有从i连向j的有向边,1表示有一条从i到j的有向边。
【输出格式】
输出1行1个整数,表示这个有向图的树形图个数。
【样例输入】
count.in
4
0100
0010
0001
1000
【样例输出】
count.out
4
【数据规模和约定】
#include <cstdio> int fa[15]; char s[15][15]; int n; int root; int ans; int get(int x){ while (fa[x]!=x) x=fa[x]; return x; } void dfs(int d){ if (root==d){ dfs(d+1); return; } if (d==n) ans++; for (int i=0;i<n;i++){ if (s[i][d]=='1' && get(i)!=get(d)){ fa[d]=i; dfs(d+1); fa[d]=d; } } } int main(){ freopen("count.in","r",stdin); freopen("count.out","w",stdout); scanf("%d",&n); for (int i=0;i<n;i++) scanf("%s",s[i]); for (int i=0;i<n;i++) fa[i]=i; for (root=0;root<n;root++) dfs(0); printf("%d\n",ans); return 0; }