A. 24 Game
题目链接
http://codeforces.com/contest/468/problem/A
题目大意
给你数字 1...n ,每次操作时,你可以从数字中选出两个数做加或减或乘操作,得到一个结果并放回数字堆中。直到最后只剩下一个数字,现在要让最后留下来的那个数字是24,问是否存在一种操作方案,并输出一组可行方案。
思路
显然, n<4 时无解。
n=4,5
时可以手玩出解来。
n>5
时,则可以先用
n=4,5
时的解凑出一个24,然后再凑出很多的数字1,将数字1和数字24相乘耗掉多余的数字
代码
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <algorithm>
using namespace std;
int main()
{
int n;
scanf("%d",&n);
if(n<4)
{
printf("NO\n");
return 0;
}
printf("YES\n");
if(n&1)
{
for(int i=6;i<=n;i+=2)
printf("%d - %d = 1\n",i+1,i);
printf("1 * 2 = 2\n");
printf("3 + 4 = 7\n");
printf("7 + 5 = 12\n");
printf("2 * 12 = 24\n");
for(int i=6;i<=n;i+=2)
printf("1 * 24 = 24\n");
}
else
{
for(int i=5;i<=n;i+=2)
printf("%d - %d = 1\n",i+1,i);
printf("1 + 2 = 3\n");
printf("3 + 3 = 6\n");
printf("6 * 4 = 24\n");
for(int i=5;i<=n;i+=2)
printf("1 * 24 = 24\n");
}
return 0;
}
B. Two Sets
题目链接
http://codeforces.com/contest/468/problem/B
题目大意
给你数字 p1...pn ,要你将它们分成两个集合 A,B ,使得 pi∈A,∃a−pi∈A ; pi∈B,∃b−pi∈B
思路
此题做法很多,可以用2SAT,DFS等等。这里我选择的是并查集的做法。
建立两个新的元素
pn+1,pn+2
,若在并查集中,
pi
和
pn+1
在同一集合,就表明数字
pi
必须放入集合
A
中。
在并查集中,若
若最终 pn+1,pn+2 在同一集合,显然矛盾,无解。
然后对于所有的与
pn+1
在同一集合的
pi
,都放入集合
A
中,其他的都放入集合
代码
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <algorithm>
#include <map>
#define MAXN 110000
#define MOD 300007
using namespace std;
int f[MAXN];
int findSet(int x)
{
if(f[x]==x) return x;
return f[x]=findSet(f[x]);
}
map<int,int>mp;
int n,a,b,p[MAXN],mark[MAXN],tmpmark[MAXN]; //mark[i]&1=1表示第i个数字可以放入A中,mark[i]&2=2表示第i个数字可以放入B中
int main()
{
scanf("%d%d%d",&n,&a,&b);
for(int i=1;i<=n;i++) scanf("%d",&p[i]),mp[p[i]]=i;
for(int i=1;i<=n+2;i++) f[i]=i;
for(int i=1;i<=n;i++)
{
if(mp.count(a-p[i]))
{
int roota=findSet(i),rootb=findSet(mp[a-p[i]]);
f[roota]=rootb;
}
else
{
int roota=findSet(i),rootb=findSet(n+2);
f[roota]=rootb;
}
if(mp.count(b-p[i]))
{
int roota=findSet(i),rootb=findSet(mp[b-p[i]]);
f[roota]=rootb;
}
else
{
int roota=findSet(i),rootb=findSet(n+1);
f[roota]=rootb;
}
}
if(findSet(n+1)==findSet(n+2))
{
printf("NO\n");
return 0;
}
printf("YES\n");
for(int i=1;i<=n;i++)
printf("%d ",findSet(i)==findSet(n+2));
printf("\n");
return 0;
}
C. Hack it!
题目链接
http://codeforces.com/contest/468/problem/C
题目大意
要你构造
l,r
,使得
∑ri=lf(i)moda=0
f(i)=
数字
i
的每个数位之和
思路
定义
显然在区间移动过程中,所有数字 100 到 10k−1 位的数位和没变,第 10k 位的数位和多了 x 个1,因此
于是我们可以先求出
代码
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <algorithm>
using namespace std;
typedef long long int LL;
int main()
{
LL a;
scanf("%I64d",&a);
LL t=(5*(9*(18*(((LL)1e17)%a)%a)%a)%a+1)%a; //solve(1,1e18)mod a
printf("%I64d %I64d\n",1+a-t,(LL)1e18+a-t);
return 0;
}