A - Odd Divisor
Time limit: 2000 ms
Memory limit: 262144 kB
Source: Codeforces Round #697 (Div. 3)
Tags: math number theory *900
Editorial: Announcement Tutorial
You are given an integer \(n\). Check if \(n\) has an odd divisor, greater than one (does there exist such a number \(x (x>1)\) that \(n\) is divisible by \(x\) and \(x\) is odd).
For example, if \(n=6\), then there is \(x=3\). If \(n=4\), then such a number does not exist.
Input
The first line contains one integer \(t (1\leqslant t\leqslant 10^4)\) — the number of test cases. Then \(t\) test cases follow.
Each test case contains one integer \(n(2\leqslant n\leqslant 10^14)\).
Please note, that the input for some test cases won't fit into \(32\)-bit integer type, so you should use at least \(64\)-bit integer type in your programming language.
Output
For each test case, output on a separate line:
-
YES
if \(n\) has an odd divisor, greater than one; -
NO
otherwise.
You can output YES
and NO
in any case (for example, the strings yEs
, yes
, Yes
and YES
will be recognized as positive).
Example
Input
6
2
3
4
5
998244353
1099511627776
Output
NO
YES
NO
YES
YES
NO
题目大意
给定一个整数 \(n\),求是否存在 奇数 \(x(x>1)\) 满足 \(x|n\)(\(x\)整除\(n\))。
PZ's Solution
1.如果\(n\)为奇数,那么一定存在\(x\)满足条件(或者说,\(x\)甚至可以等于\(n\),所以一定成立);
2.对于\(n\)为偶数的情况,可以得到\(n=2*m\),如果\(m\)还是一个偶数,则\(m=2*z\cdots\)
3.可以通过对\(n\)进行不断除\(2\)的操作,检查最后的\(n\%2\)是否等于\(1\);
4.可以对除\(2\)这个操作进行压缩,直接预处理pre[i]
数组代表\(2^i\),可以得到:
若整数\(n\)不为\(2\)的整数次方,则必然存在奇数 \(x(x>1)\) 满足 \(x|n\)(\(x\)整除\(n\))
- TAG:数学
PZ.cpp
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int T;
long long pre[64],n;
bool f;
int main(){
pre[0]=1;
for(int i=1;i<=63;++i)
pre[i]=pre[i-1]*2;
scanf("%d",&T);
while(T--){
f=0;
scanf("%lld",&n);
if(n%2==1) puts("YES");
else{
for(int i=1;i<=63;++i)
if(n==pre[i]){
f=1;
puts("NO");
break;
}
if(f==0) puts("YES");
}
}
return 0;
}
B - String LCM
Time limit: 2000 ms
Memory limit: 262144 kB
Source: Educational Codeforces Round 102 (Rated for Div. 2)
Tags: brute force math number theory strings *1000
Editorial: Announcement Tutorial
Let's define a multiplication operation between a string \(a\) and a positive integer \(x: a⋅x\) is the string that is a result of writing \(x\) copies of \(a\) one after another. For example, "abc" ⋅ 2 = "abcabc", "a" ⋅ 5 ="aaaaa".
A string \(a\) is divisible by another string \(b\) if there exists an integer \(x\) such that \(b⋅x=a\). For example, "abababab" is divisible by "ab", but is not divisible by "ababab" or "aa".
LCM of two strings \(s\)and \(t\) (defined as \(LCM(s,t)\)) is the shortest non-empty string that is divisible by both \(s\) and \(t\).
You are given two strings \(s\) and \(t\). Find \(LCM(s,t)\) or report that it does not exist. It can be shown that if \(LCM(s,t)\) exists, it is unique.
Input
The first line contains one integer \(q (1\leqslant q \leqslant 2000)\) — the number of test cases.
Each test case consists of two lines, containing strings \(s\)
and \(t (1\leqslant |s|,|t| \leqslant 20)\). Each character in each of these strings is either 'a' or 'b'.
Output
For each test case, print \(LCM(s,t)\) if it exists; otherwise, print -1
. It can be shown that if \(LCM(s,t)\) exists, it is unique.
Example
Input
3
baba
ba
aa
aaa
aba
ab
Output
baba
aaaaaa
-1
Note
In the first test case, "baba" = "baba" ⋅ \(1\) = "ba" ⋅ \(2\).
In the second test case, "aaaaaa" = "aa" ⋅ \(3\) ="aaa" ⋅ \(2\).
题目大意
对于一个字符串\(s\)和一个正整数\(x\),定义\(s · x=\sum_{i=1}^{x}s\);
给定两个字符串\(s\)和\(t\),求是否有一个字符串 同时满足\(s · x\)和\(t · y\)(\(x,y\)为任意正整数);
如果存在,称此字符串为\(LCM(s,t)\),且此字符串一定唯一。
PZ's Solution
1.没想到什么特别好的字符串算法,所以直接暴力枚举吧;
2.因为\(LCM(s,t)\)的长度确定,且一定为\(s\)和\(t\)的长度的倍数;
3.不断比较当前拼成的两个字符串,哪个短哪个再加上其原本的字符串,直到两个字符串长度相等;
4.然后比较两个字符串是否相同,按照情况输出即可。
ps.本质上,就是找出了\(s\)的长度 和 \(t\)的长度 ,这两个数的\(LCM\)(最小公倍数),再将字符串补全,进行判断即可;
- TAG:模拟
PZ.cpp
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int q;
string a,b,A,B;
int main(){
scanf("%d",&q);
while(q--){
cin>>a>>b;
A=a;
B=b;
while(a.size()!=b.size()){
if(a.size()<b.size()) a=a+A;
else b=b+B;
}
if(a!=b) puts("-1");
else cout<<a<<endl;
}
return 0;
}
C - Even-Odd Game
Time limit: 2000 ms
Memory limit: 262144 kB
Source: Codeforces Round #693 (Div. 3)
Tags: dp games greedy sortings *1200
Editorial: Announcement Tutorial
During their New Year holidays, Alice and Bob play the following game using an array \(a\) of \(n\) integers:
- Players take turns, Alice moves first.
- Each turn a player chooses any element and removes it from the array.
- If Alice chooses even value, then she adds it to her score. If the chosen value is odd, Alice's score does not change.
- Similarly, if Bob chooses odd value, then he adds it to his score. If the chosen value is even, then Bob's score does not change.
If there are no numbers left in the array, then the game ends. The player with the highest score wins. If the scores of the players are equal, then a draw is declared.
For example, if \(n=4\) and \(a =[5,2,7,3]\), then the game could go as follows (there are other options):
-
On the first move, Alice chooses \(2\) and get two points. Her score is now \(2\). The array \(a\) is now \([5,7,3]\).
-
On the second move, Bob chooses \(5\) and get five points. His score is now \(5\). The array \(a\) is now \([7,3]\).
-
On the third move, Alice chooses \(7\) and get no points. Her score is now \(2\). The array \(a\) is now \([3]\).
-
On the last move, Bob chooses \(3\) and get three points. His score is now \(8\). The array \(a\) is empty now.
-
Since Bob has more points at the end of the game, he is the winner.
You want to find out who will win if both players play optimally. Note that there may be duplicate numbers in the array.
Input
The first line contains an integer \(t (1\leqslant t\leqslant 10^4)\) — the number of test cases. Then \(t\) test cases follow.
The first line of each test case contains an integer \(n(1\leqslant n\leqslant 2⋅10^5)\) — the number of elements in the array \(a\).
The next line contains \(n\) integers \(a_1,a_2,…,a_n (1 \leqslant a_i \leqslant 10^9)\) — the array \(a\) used to play the game.
It is guaranteed that the sum of \(n\) over all test cases does not exceed \(2⋅10^5\).
Output
For each test case, output on a separate line:
-
Alice
if Alice wins with the optimal play; -
Bob
if Bob wins with the optimal play; -
Tie
, if a tie is declared during the optimal play.
Example
Input
4
4
5 2 7 3
3
3 2 1
4
2 2 2 2
2
7 8
Output
Bob
Tie
Alice
Alice
题目大意
给定一个数组\(a\),Alice和Bob会进行如下的游戏:
-
Alice先手,从数组中拿取任意一个数\(x\),如果\(x\)为偶数,则Alice得\(x\)分,反之Alice不得分;
-
随后是Bob,从数组中拿取任意一个数\(x\),如果\(x\)为奇数,则Bob得\(x\)分,反之Bob不得分;
-
依此轮换,直到数组\(a\)被取完,比较谁的得分更高。
PZ's Solution
1.因为能从数组中任意拿数,那么拿数的顺序就很关键;
2.考虑直接将数组从大到小排序,让Alice和Bob按照顺序拿数,这样的好处是:
1).如果拿到自己能加分的数,将会尽可能地大;
2).如果拿到不能加分的数,也会因为其很大,会让对手丧失拿高分的机会;
- TAG:贪心
PZ.cpp
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int T,n,a[200005];
long long Alice,Bob;
bool cmp(int x,int y){ return x>y; }
int main(){
scanf("%d",&T);
while(T--){
Alice=Bob=0;
scanf("%d",&n);
for(int i=1;i<=n;++i) scanf("%d",&a[i]);
sort(a+1,a+1+n,cmp);
for(int i=1;i<=n;++i){
if(i%2==1){
if(a[i]%2==0) Alice+=a[i];
}else
if(a[i]%2==1) Bob+=a[i];
}
if(Alice>Bob) puts("Alice");
else if(Bob>Alice) puts("Bob");
else puts("Tie");
}
return 0;
}
D - Nezzar and Symmetric Array
Time limit: 2000 ms
Memory limit: 524288 kB
Source: Codeforces Round #698 (Div. 2)
Tags: implementation math sortings *1700
Editorial: Announcement (en) Tutorial (en)
Long time ago there was a symmetric array \(a_1,a_2,…,a_{2n}\) consisting of \(2n\) distinct integers. Array \(a_1,a_2,…,a_{2n}\) is called symmetric if for each integer \(1\leqslant i \leqslant 2n\), there exists an integer \(1 \leqslant j \leqslant 2n\) such that \(a_i=−a_j\).
For each integer \(1\leqslant i \leqslant 2n\), Nezzar wrote down an integer \(d_i\) equal to the sum of absolute differences from ai to all integers in \(a\), i. e. \(d_i=\sum_{j=1}^{2n}|a_i−a_j|\).
Now a million years has passed and Nezzar can barely remember the array \(d\)
and totally forget \(a\). Nezzar wonders if there exists any symmetric array \(a\) consisting of \(2n\). distinct integers that generates the array \(d\).
Input
The first line contains a single integer \(t (1\leqslant t\leqslant 10^5)\) — the number of test cases.
The first line of each test case contains a single integer \(n(1\leqslant n\leqslant 10^5)\).
The second line of each test case contains \(2n\) integers \(d_1,d_2,…,d_{2n} (0 \leqslant d_i \leqslant 10^{12})\).
It is guaranteed that the sum of \(n\) over all test cases does not exceed \(10^5\).
Output
For each test case, print YES
in a single line if there exists a possible array \(a\). Otherwise, print NO
.
You can print letters in any case (upper or lower).
Example
Input
6
2
8 12 8 12
2
7 7 9 11
2
7 11 7 11
1
1 1
4
40 56 48 40 80 56 80 48
6
240 154 210 162 174 154 186 240 174 186 162 210
Output
YES
NO
NO
NO
NO
YES
Note
In the first test case, \(a=[1,−3,−1,3]\) is one possible symmetric array that generates the array \(d=[8,12,8,12]\).
In the second test case, it can be shown that there is no symmetric array consisting of distinct integers that can generate array \(d\).
题目大意
定义数组\(a\)的大小为\(2n\),且对于任意的\(a_i(1\leqslant i \leqslant 2n)\),一定满足\(a_i=-a_j(1\leqslant j \leqslant 2n)\)
定义数组\(d\)的大小为\(2n\),且满足\(d_i=\sum_{j=1}^{2n}|a_i−a_j|(1\leqslant i \leqslant 2n)\).
现在给出数组\(d\),求满足定义的数组\(a\)是否存在?
PZ's Solution
本题解可以结合Tisfy的Codeforces Round #698 (Div. 2)-C. Nezzar and Symmetric Array-题解和zjj0624的C. Nezzar and Symmetric Array(数学)一起研究;
1.对于\(n=2\)的情况,设数组\(a=[-a_{2},-a_{1},a_{1},a_{2}](a_1<a_2)\)
设数组\(d=[d_{-2},d_{-1},d_1,d_2]\),则可以得到:
\(d_{-2}=4a_2\),\(d_{-1}=2a_2+2a_1\),\(d_1=2a_2+2a_1\),\(d_2=4a_2\)
可以发现,由于数组\(a\)具有对称性,得到的数组\(d\)也是具有对称性的,所以只需要研究一半即可;
对于\(n=3\)的情况,设\(a_1<a_2<a_3\),则有
\(d_1=2a_1+2a_2+2a_3\),\(d_2=4a_2+2a_3\),\(d_3=6a_3\)
……
2.观察规律,可以得到,设\(a_n\)为数组\(a\)的最大的数,则\(d_n\)也一定为数组\(d\)最大的数,且有关系\(d_n=2n\times a_n\),这样就能通过\(d_n\)求出\(a_n\);
3.观察\(n=3\)时的\(d_2=4a_2+2a_3\),通过2.能将\(a_3\)求出,那么就能从\(d_2\)求出\(a_2\);
4.这样层层剥茧,就能还原出所有正数的\(a_i\);
伪代码
输入数组d;
将数组d从大到小排序;//数组a实际上没有顺序的,则数组d实际上也是没有顺序的
for(d每两两一对){//由于数组a的对称性
if(当前di出现了不止两次){
puts("NO");
return 0;
}//因为数组a中的数唯一,那么数组d中的数就只能出现两次
将当前ai从di中求出;
if(di求不出ai || ai<=0){
puts("NO");
return 0;
}
}
puts("YES");
return 0;
- TAG:思维;数学
PZ.cpp
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<map>
using namespace std;
#define ll long long
int T,n,cnt;
ll d[200005],suma,nowa;
bool f;
bool cmp(ll x,ll y){ return x>y; }
int main(){
scanf("%d",&T);
while(T--){
map<int,int>vis;
suma=f=0;
scanf("%d",&n);
for(int i=1;i<=2*n;++i){
scanf("%lld",&d[i]);
if(d[i]%2==1) f=1;
d[i]/=2;
}
sort(d+1,d+1+2*n,cmp);
cnt=n;
for(int i=1;i<=n;++i){
int x=2*(i-1)+1,y=2*(i-1)+2;
if(d[x]!=d[y]) f=1;
if(d[x-1]==d[x]||d[y]==d[y+1]) f=1;
nowa=(d[x]-suma)/cnt;
if(vis[nowa]||nowa<=0||((d[x]-suma)%cnt!=0)) f=1;
suma+=nowa;
vis[nowa]=1;
--cnt;
}
if(f) puts("NO");
else puts("YES");
}
return 0;
}
E - Piggy-Bank
Time limit: 1000 ms
Memory limit: 32768 kB
OS: Windows
Source: Central Europe 1999
Before ACM can do anything, a budget must be prepared and the necessary financial support obtained. The main income for this action comes from Irreversibly Bound Money (IBM). The idea behind is simple. Whenever some ACM member has any small money, he takes all the coins and throws them into a piggy-bank. You know that this process is irreversible, the coins cannot be removed without breaking the pig. After a sufficiently long time, there should be enough cash in the piggy-bank to pay everything that needs to be paid.
But there is a big problem with piggy-banks. It is not possible to determine how much money is inside. So we might break the pig into pieces only to find out that there is not enough money. Clearly, we want to avoid this unpleasant situation. The only possibility is to weigh the piggy-bank and try to guess how many coins are inside. Assume that we are able to determine the weight of the pig exactly and that we know the weights of all coins of a given currency. Then there is some minimum amount of money in the piggy-bank that we can guarantee. Your task is to find out this worst case and determine the minimum amount of cash inside the piggy-bank. We need your help. No more prematurely broken pigs!
Input
The input consists of \(T\) test cases. The number of them (\(T\)) is given on the first line of the input file. Each test case begins with a line containing two integers \(E\) and \(F\). They indicate the weight of an empty pig and of the pig filled with coins. Both weights are given in grams. No pig will weigh more than \(10\) kg, that means \(1 \leqslant E \leqslant F \leqslant 10000\). On the second line of each test case, there is an integer number \(N (1 \leqslant N \leqslant 500)\) that gives the number of various coins used in the given currency. Following this are exactly N lines, each specifying one coin type. These lines contain two integers each, \(P\) and \(W (1 \leqslant P \leqslant 50000, 1 \leqslant W \leqslant 10000)\). \(P\) is the value of the coin in monetary units, \(W\) is it's weight in grams.
Output
Print exactly one line of output for each test case. The line must contain the sentence The minimum amount of money in the piggy-bank is X.
where X
is the minimum amount of money that can be achieved using coins with the given total weight. If the weight cannot be reached exactly, print a line This is impossible.
.
Sample Input
3
10 110
2
1 1
30 50
10 110
2
1 1
50 30
1 6
2
10 3
20 4
Sample Output
The minimum amount of money in the piggy-bank is 60.
The minimum amount of money in the piggy-bank is 100.
This is impossible.
题目大意
给一个容量为\(E-F\)的背包,给\(N\)种物品,每种物品的价值为\(P\)、大小为\(W\),物品数量无限,求此背包装满后,最小价值为多少?
PZ's Solution
1.经典的完全背包,不过有些许不同;
2.初始化f[]
为无限大,有状态转移方程:
- TAG:动态规划;完全背包
PZ.cpp
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int T,E,F,M,N,P,W,f[10005];
int main(){
scanf("%d",&T);
while(T--){
memset(f,0x3f,sizeof(f));
f[0]=0;
scanf("%d %d",&E,&F);
M=F-E;
scanf("%d",&N);
for(int i=1;i<=N;++i){
scanf("%d %d",&P,&W);
for(int j=W;j<=M;++j)
f[j]=min(f[j],f[j-W]+P);
}
if(f[M]==0x3f3f3f3f) puts("This is impossible.");
else printf("The minimum amount of money in the piggy-bank is %d.\n",f[M]);
}
return 0;
}
F - 悼念512汶川大地震遇难同胞——珍惜现在,感恩生活
Time limit: 1000 ms
Memory limit: 32768 kB
OS: Windows
Source: 2008-06-18《 ACM程序设计》期末考试——四川加油!中国加油!
急!灾区的食物依然短缺!
为了挽救灾区同胞的生命,心系灾区同胞的你准备自己采购一些粮食支援灾区,现在假设你一共有资金n元,而市场有m种大米,每种大米都是袋装产品,其价格不等,并且只能整袋购买。
请问:你用有限的资金最多能采购多少公斤粮食呢?
后记:
人生是一个充满了变数的生命过程,天灾、人祸、病痛是我们生命历程中不可预知的威胁。
月有阴晴圆缺,人有旦夕祸福,未来对于我们而言是一个未知数。那么,我们要做的就应该是珍惜现在,感恩生活——
感谢父母,他们给予我们生命,抚养我们成人;
感谢老师,他们授给我们知识,教我们做人
感谢朋友,他们让我们感受到世界的温暖;
感谢对手,他们令我们不断进取、努力。
同样,我们也要感谢痛苦与艰辛带给我们的财富~
Input
输入数据首先包含一个正整数\(C\),表示有\(C\)组测试用例,每组测试用例的第一行是两个整数\(n\)和\(m(1\leqslant n \leqslant 100, 1 \leqslant m \leqslant 100)\),分别表示经费的金额和大米的种类,然后是\(m\)行数据,每行包含\(3\)个数\(p\),\(h\)和\(c(1\leqslant p\leqslant 20,1\leqslant h\leqslant 200,1\leqslant c \leqslant 20)\),分别表示每袋的价格、每袋的重量以及对应种类大米的袋数。
Output
对于每组测试数据,请输出能够购买大米的最多重量,你可以假设经费买不光所有的大米,并且经费你可以不用完。每个实例的输出占一行。
Sample Input
1
8 2
2 100 4
4 100 2
Sample Output
400
PZ's Solution
1.经典的多重背包,这里采用二进制拆分来解决;
2.因为任何一个数都能转化成二进制的形式,所以可以将\(c\)袋大米拆为\(2^0\)、\(2^1\)、……、\(2^x\)袋;
3.这样,不管买多少袋这种大米就都能用表示了;
- TAG:动态规划;多重背包
PZ.cpp
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define maxn 100005
int C,n,m,p,h,c,M,ans,P[maxn],H[maxn],f[maxn];
int main(){
scanf("%d",&C);
while(C--){
memset(f,0,sizeof(f));
M=ans=0;
scanf("%d %d",&n,&m);
for(int i=1;i<=m;++i){
scanf("%d %d %d",&p,&h,&c);
for(int j=1;j<=c;j<<=1){
P[++M]=p*j;
H[M]=h*j;
c-=j;
}
if(c){
P[++M]=p*c;
H[M]=h*c;
}
}
for(int i=1;i<=M;++i)
for(int j=n;j>=P[i];--j)
f[j]=max(f[j],f[j-P[i]]+H[i]);
printf("%d\n",f[n]);
}
return 0;
}
赛后总结
1.A题和B题还是比较简单的,在此不过多讨论了;
2.其实C题的贪心是隐藏在规则之中的,能从数组中任意取数是关键,要想到拿了不加分 对 己方的益处;
3.D题反而是这次排位赛最难的题,对条件的判断十分苛刻,光是能推出怎么从\(d\)推出\(a\)还不够,还需要直到怎么才不能从\(d\)推出\(a\);
4.E题和F题是背包的模板,刚好对应了上周的背包知识点的讲解;
ps.2021年的2月来了,转眼间2021年都过去了\(\frac{1}{12}\)了,时光飞逝,要好好努力了!