首页 > 代码库 > Codeforces Round #268 (Div. 1) 题解
Codeforces Round #268 (Div. 1) 题解
A:24 Game
题意:给一个n,求从1到n通过加减乘除得到24的方法。
题解:不难想到n<4时候肯定是无解的,
n=4时候 1+2=3 3+3=6 6*4=24
n=5时候1*5=5 5-2=3 3+3=6 6*4=24
当n>5时候我们可以让n-(n-1)=1 1*1=1 这样就把1~n变成了1~n-2
所以对于任意给定的n,我们把(5~n)这段的数相邻的相减变成1最终转换成用1~4或者1~5构造答案即可。
1 #include <cstdio> 2 3 #include <cmath> 4 5 #include <iostream> 6 7 #include <algorithm> 8 9 #include <cstring>10 11 12 13 using namespace std;14 15 int n;16 17 void work(int x)18 19 {20 21 if (x==4) 22 23 {24 25 printf("1 + 2 = 3\n3 + 3 = 6\n4 * 6 = 24\n");26 27 return;28 29 }30 31 if (x==5)32 33 {34 35 printf("1 * 5 = 5\n5 - 2 = 3\n3 + 3 = 6\n6 * 4 = 24\n");36 37 return;38 39 }40 41 printf("%d - %d = 1\n1 * 1 = 1\n",x,x-1);42 43 work(x-2);44 45 }46 47 int main()48 49 {50 51 scanf("%d",&n);52 53 if (n<4)54 55 {56 57 printf("NO\n");58 59 return 0;60 61 }62 63 printf("YES\n");64 65 work(n);66 67 return 0;68 69 }
B:Two Sets
题意:给出n个数p1~pn 要求把这N个数划分成两个集合,要求若X∈A 则a-x∈A 若X∈B 则b-x属于B,a,b为给定得数。
题解:用一个map记录每个数是否出现过,若对于某个pi a-pi不在这列数中,我们就只能把pi放到B集合中,所以用一个队列记录必然出现在B集合中的数,
每次取出队头元素X,检查b-X是否在p中出现,若出现也要加入此队列,再加入b-X的同时易知a-(b-X)必然也只能出现在集合B,也要同时加入队列。
1 #include <cstdio> 2 3 #include <iostream> 4 5 #include <algorithm> 6 7 #include <cmath> 8 9 #include <cstring>10 11 #include <queue>12 13 #include <map>14 15 using namespace std;16 17 map<int,int> pos;18 19 int n,a,b,ans[500000],x[500000];20 21 int main()22 23 {24 25 queue<int> q;26 27 scanf("%d%d%d",&n,&a,&b);28 29 for (int i=1;i<=n;++i) 30 31 {32 33 scanf("%d",&x[i]);34 35 pos[x[i]]=i;36 37 }38 39 for (int i=1;i<=n;++i)40 41 {42 43 if (pos[a-x[i]]==0)44 45 {46 47 ans[i]=1;48 49 q.push(x[i]);50 51 }52 53 }54 55 while (!q.empty())56 57 {58 59 int now=q.front();60 61 q.pop();62 63 if (pos[b-now]==0) 64 65 {66 67 printf("NO\n");68 69 return 0;70 71 }72 73 if (ans[pos[b-now]]==1) continue;74 75 ans[pos[b-now]]=1;76 77 if (pos[a-b+now]!=0)78 79 {80 81 ans[pos[a-b+now]]=1;82 83 q.push(a-b+now);84 85 }86 87 }88 89 printf("YES\n");90 91 for (int i=1;i<=n;++i) printf("%d ",ans[i]);92 93 return 0;94 95 }
C:Hack it!
题意:定义f(x)为x的各位数字之和,比如f(1234)=1+2+3+4=10,一个人用如下算法计算
sum=
ans = solve(l, r) % a;
if (ans <= 0)
ans += a;
当ans=0时会出现错误,对于给定的a,我们要构造一个L,R来hack他。
gy神犇给我讲的
我们来观察l=1 r=1e18的时候的sum值
l r每当+1的时候 我们发现sum值加了1!因为r加1后后面几位即为l不加1时候的数,所以每次加1即把整个数列往前推了一位,然后r变成了1000...L!于是L,R每往后加1,sum就加1,于是先求出来l=1 r=1e18的sum值后挪(a-sum)次即可!r开到足够大目的在于这样不用考虑进位问题,否则r最前面就不是1,也不能保证后面出现L了。巧妙地构造~
关于sum的算法:令ai=(1~10^i)-1的sum值
a1=45
a2=10*a1+45*10
...
an=10*an-1+45*10^i
得到an=45*n*10^(n-1)
a18=81*1e18
所以sum=(a18+1)%a;问题得到解决。
1 #include <cstdio> 2 3 #include <cmath> 4 5 #include <iostream> 6 7 #include <cstring> 8 9 #include <algorithm>10 11 12 13 using namespace std;14 15 typedef long long LL;16 17 LL l,r,a,ans;18 19 int main()20 21 {22 23 l=1;r=1e18;24 25 scanf("%I64d",&a);26 27 ans=((3*(3*(3*(3*(5*(2*((LL)1e17%a))%a)%a)%a)%a)%a)%a+1)%a;28 29 printf("%I64d %I64d",l+a-ans,r+a-ans);30 31 return 0;32 33 }
Codeforces Round #268 (Div. 1) 题解