咳咳因为我们老大觉得太简单了,所以这个只有自己做了qwq
两个小时的比赛,除去自己的智障、还有好多没学过的有点无奈==
第三题看了dalao的代码qaq,然后第五题实在没时间看...
#include <bits/stdc++.h>
using namespace std;
/*【平分披萨】
正好有n个Shiro的朋友在这里,要把披萨分成n+1份。
她希望切片的大小和形状完全一样,想用最少的直切来切披萨。
切是一个直的线段,它可能在披萨里面或外面结束。你能帮助Shiro解决这个问题吗?
分析》0≤n≤10^18 用longlong
根据蛋糕的对称性,当n为奇数时,需要切n刀才可
而当n为偶数时,只需要切n/2刀 [特判等于一的情况!!] */
int main(){
long long n,ans=0;
cin>>n; n+=1;
if(n==1) n=0;//longlong类型的1 特判
if(n%2==0) n/=2;//除二的过程中已经保留了分割的一刀
cout<<n<<endl;
return 0;
}
#include <bits/stdc++.h>
using namespace std;
/*【寻宝游戏】
题意》给出三个字符串,表示三个人初始拥有的串。进行n次操作。
每次操作任意替换一个字母,问每串中{曾经出现的个数最多的相同的字符}谁更多。
分析》找初始串个数最多的字母,其他的按全部步数转换成单个字母,
*注意*初始的字符串中即使是最多元素也不会计入统计,至少一次操作后才能记入,
所以需要特判 if(ans==len&&n==1) return len-1; 情况 */
const int inf=0x3f3f3f3f;
int n,len,max1,max2,max3;
void print(){ //输出赢家
if(max1>max2&&max1>max3) cout<<"Kuro"<<endl;
else if(max2>max1&&max2>max3) cout<<"Shiro"<<endl;
else if(max3>max1&&max3>max2) cout<<"Katie"<<endl;
else cout<<"Draw"<<endl;
}
int work(){
char ss[200005]; scanf("%s",ss);
int cnt[300]; memset(cnt,0,sizeof(cnt)); //统计字符个数
int ans=-1,len=strlen(ss);
for(int i=0;i<len;i++){
cnt[ss[i]]++; ans=max(ans,cnt[ss[i]]);
}
if(ans==len&&n==1) return len-1;//初始字符串是最多元素,但不会计入统计
else if(len-ans>=n) return ans+n;//不能达到一整串完全相同
else return len; //曾经有情况是一整串完全相同
}
int main(){
scanf("%d",&n); //n次变换
max1=work(); max2=work(); max3=work(); print();
return 0;
}
#include <bits/stdc++.h>
using namespace std;
/*【城镇道路】
题意》hss生活在Iceland,n个城镇都有n-1个连接别的城镇的双向道路。
jy会选择两个城镇(u,v)和从u到v的最短路径(注意,(u,v)被认为是不同于(v,u))。
在Iceland有两个特殊的城镇,叫做Florence(用索引x来表示)<--坠喜欢的城市!!!
和hangzhou(用索引y表示)。Florence是一个有许多强烈气味的花的城镇,
而hangzhou是另一个有许多蜜蜂居住的城镇。特别是,如果从u到v的路径上,
当jy到达了Florence后,他就会到达hangzhou,Kuro想知道他可以选择多少个城市(u,v)。
既然他不是很聪明(??),他请你帮他解决这个问题。//这个题意实在无能为力...
题意简化》给定一个n个点,n-1条边的无向图,途中任意两点联通,
并给出节点x,y,计算图上两点(u,v)之间的最短路径依次经过x,y的对数,
(u,v)与(v,u)视作不同一对,求总对数-符合条件的对数 */
//以下是来自 https://blog.csdn.net/WangYC123456/article/details/80318442 的分析和代码
/*分析》无向图,可以将图中任意节点作为根建树->将y作为树根,x则是树y的某一节点
设s[i]为{子树i的size(包括i本身)},节点z为(y,x)路径上y的儿子节点 //↓↓↓用树的数量大小表示方案数
符合条件的对数为(y,x)路径两端的节点数相乘,即s[x]*(s[y]-s[z]),用n(n-1)减去就可以得出答案(longlong)
//邻接表存图,s[]用递归的dfs完成,寻找而节点z同样用dfs的递归标记 */
#define ll long long
const int MAXN=3e5+10;
int n,x,y,z;
int last[MAXN],num;
int size[MAXN];
bool tag[MAXN],vis[MAXN];
inline int in(){ //读入优化
int x=0,flag=1;
char ch=getchar();
while(ch<'0'||ch>'9'){ if(ch=='-') flag=-1; ch=getchar(); }
while(ch>='0'&&ch<='9'){ x=x*10+ch-'0'; ch=getchar(); }
return x*flag;
}
struct Edge { //邻接表
int nex,to;
}e[MAXN*2];
void adds(int from,int to){ //建边
e[++num]=(Edge){last[from],to};
last[from]=num;
}
int dfs(int u){
vis[u]=true; size[u]++;
if(u==x) tag[u]=true;
for(int i=last[u];i;i=e[i].nex){
int v=e[i].to; //下一条边
if (!vis[v]){
dfs(v); size[u]+=size[v]; //子树值合并
if(tag[v]){ tag[u]=1; if(u==y) z=v; }
//个人理解:v=x才为true,u=y则这条路为x->y,z为子树节点
}
}
}
int main(){
n=in(); x=in(); y=in();
for(int i=1;i<n;i++)
{
int u=in(),v=in();
adds(u,v); adds(v,u);
}
dfs(y); cout<<(ll)n*(n-1)-(ll)size[x]*(size[y]-size[z])<<endl;
return 0;
}
D. Kuro and GCD and XOR and SUM
http://codeforces.com/contest/979/problem/D
#include <bits/stdc++.h>
using namespace std;
/*【数学游戏】
游戏关于最大公约数(GCD),XOR值和两个数字的和。
jy非常喜欢这款游戏,所以他每天都会按照级别解决问题。
他今天休假(过生日去辣~\(≧▽≦)/~)无法继续自己的连胜。
由于hss是一个可靠的人,jy请她在这天来他家玩游戏。
最初,有一个空阵列a。游戏由两种类型的q任务组成。
第一种类型要求hss给a添加一个数字ui。
第二种类型要求hss找到一个存在的数v,满足ki|GCD(xi,v),xi+v≤si;且使xi⊕v最大,
其中⊕表示按位[异或运算],GCD(c,d )表示最大公约数,y|x表示x可以被y整除。
如果没有找到这样的数字,则报告-1。
hss要自动准确地完成游戏中的任务,以满足她亲爱的jy。 */
/*【题意简析】
有n个操作,操作1代表往集合里面加入一个数字x,
操作2会给出三个数字x,k,s,然后对于每一个2操作,要求从集合中找一个数v,
满足下面的条件:gcd(x,v)%k==0 v≤s-x , 使x⊕v的值最大。
1.gcd(x,v)%k==0,那么必然有x%k==0和v%k==0,首先判断一下x%k成立与否。
2.01字典树可以很容易找出一堆数里面于一个数{异或值最大}的数(0找1,1找0),
又因为当k==1的时候gcd(x,v)%k==0,这个条件一定满足,
所以问题转化成从集合中找出小于等于s-x范围内的异或值最大的数。
(用minn[]数组标记字典树中当前节点插入进来的最小值)
3.k!=1时,v一定是k的倍数,在s−x范围内{枚举k的倍数},不断更新答案。 */
//首先某蒟蒻表示自己并没有学过字典树qaq
//思路和代码来自 https://blog.csdn.net/riba2534/article/details/80344026 感谢dalao
#define mem(a, b) memset(a, b, sizeof(a))
#define lson l, m, rt << 1
#define rson m + 1, r, rt << 1 | 1
#define inf 0x3f3f3f3f
typedef long long ll;
const int N = 2e5 + 10;
int a[N];
struct dicTree{
struct node{
int next[2];
} tree[N * 32];
int minn[N]; //记录当前节点插入进来的最小的值
int root, sz;
int newnode(){
tree[sz].next[0] = tree[sz].next[1] = -1;
sz++;
return sz - 1;
}
void init(){
sz = 0;
mem(minn, inf);
root = newnode();
}
void insert(int x){
int p = x;
int now = root;
minn[now] = min(minn[now], p);
for (int i = 31; i >= 0; i--){
int to = (x >> i) & 1;
if (tree[now].next[to] == -1)
tree[now].next[to] = newnode();
now = tree[now].next[to];
minn[now] = min(minn[now], p);
}
}
int find(int x, int p){
int now = root;
if (minn[now] > p)
return -1;
for (int i = 31; i >= 0; i--){
int to = (x >> i) & 1;
if (tree[now].next[to ^ 1] != -1
&& minn[tree[now].next[to ^ 1]] <= p)
to ^= 1;
now = tree[now].next[to];
}
return minn[now];
}
} ac;
int main(){
//freopen("in.txt", "r", stdin);
int t, op, x, k, s;
ac.init();
scanf("%d", &t); while (t--){
scanf("%d", &op);
if (op == 1){
scanf("%d", &x); a[x] = 1;
ac.insert(x);
}
else{
scanf("%d%d%d", &x, &k, &s);
if (x % k != 0){
puts("-1"); continue;
}
if (k == 1){
printf("%d\n", ac.find(x, s - x));
continue;
}
int maxx = -1, ans = -1;
for (int v = k; v <= s - x; v += k)
if (a[v] && (v ^ x) > maxx) {
maxx = v ^ x; ans = v;
}
printf("%d\n", ans);
}
}
return 0;
}
/* //来自同一位大佬的集合set做法(这个我也不会就不多说了w)
#define mem(a, b) memset(a, b, sizeof(a))
#define lson l, m, rt << 1
#define rson m + 1, r, rt << 1 | 1
#define inf 0x3f3f3f3f
typedef long long ll;
const int N = 1e5 + 10;
set<int> se[N];
int main(){
// freopen("in.txt", "r", stdin);
int n, op, x, k, s;
scanf("%d", &n);
for (int i = 1; i <= n; i++){
scanf("%d", &op);
if (op == 1){
scanf("%d", &x);
for (int i = 1; i <= (int)sqrt(x); i++)
if (x % i == 0)
{
se[i].insert(x);
se[x / i].insert(x);
}
}
else{
scanf("%d%d%d", &x, &k, &s);
int sum = -1, ans = -1;
if (x % k){
printf("%d\n", ans); continue;
}
auto it = se[k].upper_bound(s - x);
if (se[k].empty() || it == se[k].begin()){
printf("%d\n", ans);
continue;
}
--it;
for (; it != se[k].begin(); --it){
int v = *it;
if (sum > x + v) break;
if (sum < (x ^ v)){
ans = v; sum = x ^ v;
}
}
if (sum < (x ^ *it)) ans = *it;
printf("%d\n", ans);
}
}
return 0;
} */
E. Kuro and Topological Parity
http://codeforces.com/contest/979/problem/E
/* 【E. Kuro and Topological Parity】
Kuro向Katie提出挑战,只用白纸,铅笔,一把剪刀和许多箭头来制作(箭的数量无限)
纸分成n份,Shiro用某种颜色画了一些作品。具体来说,第i部分具有颜色ci,
其中ci = 0定义黑色,ci = 1定义白色,ci = -1意味着这件作品还没有被着色。
游戏的规则:玩家必须在一对不同的棋子之间放置一些箭头,这样每个箭头的起始数字小于棋子的数量。
另外,两个不同的部件只能通过最多一个箭头连接。之后,玩家必须选择颜色(0或1)为每个未上漆的作品。
将箭头和着色片段的有效方式的分数定义为交替颜色片段的数量。例如,[1→0→1→0],[0→1→0→1],[1],[0]是有效路径并将被计数。
只有当从x到y有一个箭头时,你才能从x片段到y片段。
设定奇偶校验p,其中p = 0代表“偶数”,p = 1代表“奇数”,以这样的方式放置箭头并选择颜色。
好像会有很多满足Kuro的方法。他想计算它们的数量,但这可能是一个非常大的数字。
让我们来帮助他解决他的问题,但打印它的模109+7 ,游戏如此之多,以至于他一天一天地解决关卡问题。
可悲的是,他正在休假一天,他无法继续自己的连胜。由于凯蒂是一个可靠的人,Kuro请她在这天来他家玩游戏。
最初,有一个空阵列a。游戏由两种类型的q任务组成。第一种类型要求凯蒂给a添加一个数字ui。
第二种类型要求凯蒂找到一个存在的数v,使得kiGCD(xi,v),xi +v≤si和xi⊕v被最大化,
其中⊕表示按位异或运算,GCD(c,d )表示整数c和d的最大公约数,y | x表示x可以被y整除
如果没有找到这样的数字,则报告-1。 */ //这个题考试的时候只有不到100的正确数,等我有时间再想吧qaq
——时间划过风的轨迹,那个少年,还在等你。