咳咳因为我们老大觉得太简单了,所以这个只有自己做了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
——时间划过风的轨迹,那个少年,还在等你。