9.18考试 第一题count题解

  这道题说起来挺可惜的,当时纠结是用常数大但有可能减少递归层数的模还是用常数小但递归多的回溯纠结了好半天,最终错误的选择了摸。导致T了20分,改成回溯就A了。

  先分析一下性质,我在考试的时候打表发现在数据范围内因子最多有240个,因此有可能是通过枚举因子进行计算,然后如果说对于一个块他的确可以把一棵树分为几块方法只有一种(不要问我为什么,我也不知道怎么证,但的确如此)那么我们的最坏复杂度就是O(240*n),比理论最大复杂度还多了一倍,这也是为什么当时我自己预估60分的原因,然而这就很尴尬了,这的确能过,因为我们只要搜索到一个不合法位置就可以直接return所以会快许多。而且,对于size小于当前check的我们就没有必要再去搜了,这会降低对于较大因子的时间复杂度。然后就很玄学的过了,额,过了……

 1 #include<iostream>
 2 #include<cstdlib>
 3 #include<cstdio>
 4 #include<cstring>
 5 #include<queue>
 6 #include<algorithm>
 7 #include<cmath>
 8 #include<map>
 9 #include<vector>
10 #define N 1000005
11 using namespace std;
12 int size[N],fa[N],n,a[N];
13 struct ro
14 {
15     int to,next;
16 }road[N*2];
17 int zz1,zz,sx[N];
18 void build(int x,int y)
19 {
20     zz++;
21     road[zz].to=y;
22     road[zz].next=a[x];
23     a[x]=zz;
24 }
25 void dfs(int x)
26 {
27     size[x]=1;
28     for(int i=a[x];i>0;i=road[i].next)
29     {
30         int y=road[i].to;
31         if(y==fa[x])continue;
32         fa[y]=x;
33         dfs(y);
34         size[x]+=size[y];
35     }
36 }
37 int ans=2;
38 bool yx;
39 int dfs2(int x,int l)
40 {
41     int sum=1;
42     for(int i=a[x];i>0;i=road[i].next)
43     {
44         int y=road[i].to;
45         if(y==fa[x])continue;
46         if(size[y]>=l)
47         {
48             int k=dfs2(y,l);
49             if(k==-1)
50                 return -1;
51             sum+=k;
52         }
53         else
54         {
55             sum+=size[y];
56         }
57         if(sum>l)
58         {
59             return -1;
60         }
61     }
62     if(sum==l)
63     {
64         return 0;
65     }
66     else return sum;
67 }
68 void check(int l)
69 {
70     int k=dfs2(1,l);
71     if(k!=-1)
72         ans++;
73 }
74 int main()
75 {
76     scanf("%d",&n);
77     for(int i=1;i<n;i++)
78     {
79         int x,y;
80         scanf("%d%d",&x,&y);
81         build(x,y);
82         build(y,x);
83     }
84     for(int i=2;i<n;i++)
85     {
86         if(n%i==0)
87         {
88             zz1++;
89             sx[zz1]=i;
90         }
91     }
92     dfs(1);
93     for(int i=1;i<=zz1;i++)
94         check(sx[i]);
95     printf("%d\n",ans);
96     return 0;
97 }

时间: 2024-10-19 09:24:02

9.18考试 第一题count题解的相关文章

9.18考试 第二题Dinner题解

当时初步感觉是一个类似动归或者贪心的神题,然而由于本题已经给出顺序,贪心貌似并没有什么道理,所以放弃贪心.然后又由于这是一个环的问题,我想到了"合并石子"那种环转链的思路,然后就是一个O(n^2*m)的近似背包的打法,虽然没有去打,但应该可行吧-- 然后我又发现这道题貌似可以二分答案来进行check,然后我们就需要去枚举每一次的起始点,并进行模拟,然后加了一个剪枝即如果当前点的前缀和大于当前check的值,说明我们已经在给第一个点第一份菜单时给了他第二份菜单,而这又是不可行的,否则我们

9.5 考试 第一题 礼物题解

问题 A: 礼物 时间限制: 1 Sec  内存限制: 256 MB 题目描述 夏川的生日就要到了.作为夏川形式上的男朋友,季堂打算给夏川买一些生 日礼物. 商店里一共有种礼物.夏川每得到一种礼物,就会获得相应喜悦值Wi(每种 礼物的喜悦值不能重复获得). 每次,店员会按照一定的概率Pi(或者不拿出礼物),将第i种礼物拿出来. 季堂每次都会将店员拿出来的礼物买下来.没有拿出来视为什么都没有买到,也 算一次购买. 众所周知,白毛切开都是黑的.所以季堂希望最后夏川的喜悦值尽可能地高. 求夏川最后最大

9.16考试 第一题 X国的军队题解

这道题总体来看还是比较满意的.连想带打不超过半个小时,打了不到当时基本读懂后就感觉是贪心,但贪什么很重要,当时一开始想的是贪心死亡人数,从小到大搞,然后自己造了几个小数据,还好WA了,然后又列了一个式子,直接证明了贪心.式子如下: 我们设有两个据点,一个A=x1,B=y1,另一个A=x2,b=y2. 若x1-y1>x2-y2 则先打A所需为 x1+(x2-(x1-y1))=x2+y1,先打B为x2+(x1-(x2-y2))=x1+y2. 由上式可知x1+y2>x2+y1,所以应当先打A. 其余

名校联赛DAY.2A层第一题passward题解

问题 A: Passward 时间限制: 1 Sec  内存限制: 512 MB 题目描述 你来到了一个庙前,庙牌上有一个仅包含小写字母的字符串 s. 传说打开庙门的密码是这个字符串的一个子串 t,并且 t 既是 s 的前缀又是 s的后缀并且还在 s 的中间位置出现过一次. 如果存在这样的串,请你输出这个串,如有多个满足条件的串,输出最长的那一个. 如果不存在这样的串,输出"Just a legend"(去掉引号). 输入格式: 仅一行,字符串 s. 输出格式: 如题所述 样例输入 f

9.5 考试 第二题 通讯题解

问题 B: 通讯 时间限制: 1 Sec  内存限制: 256 MB 题目描述 "这一切都是命运石之门的选择." 试图研制时间机器的机关SERN截获了中二科学家伦太郎发往过去的一条短 信,并由此得知了伦太郎制作出了电话微波炉(仮). 为了掌握时间机器的技术,SERN总部必须尽快将这个消息通过地下秘密通讯 网络,传达到所有分部. SERN共有N个部门(总部编号为0),通讯网络有M条单向通讯线路,每条线 路有一个固定的通讯花费Ci. 为了保密,消息的传递只能按照固定的方式进行:从一个已知消

认证考试第一题

namespace Test1_1{ class Program { static void Main(string[] args) { int result = 0; Console.WriteLine("请输入一个正整数:"); int n = int.Parse(Console.ReadLine()); if (n %2 == 0)//这里要注意  是求余运算  ,不能用"/" { for (int i = 0; i <= n;i+=2) { resul

C语言考试第一题详细过程

1.计算 ,并输出其结果. 思路是先设计一个函数计算阶乘,再用循环,逐个求和. #include<stdio.h> int mul(int n) { int num,i; num=1; for(i=1;i<=n;i++) num=num*i; return(num); } void main() { int i,sum=0; for(i=1;i<=10;i++) sum+=mul(i); printf("The sum is %d\n",sum); } 这个代码

LeetCode 第一题,Two Sum

今天早上起来去机房的路上还在想,一直不做算法题老是觉得不踏实.做做题总是让自己觉得自己真的在做做学习.... 这也算是一种强迫症吧. 那就从今天开始做做LeetCode,因为好久没做过了,所以第一题还是看了别人的题解和思路,算是找找感觉. 总的来说第一题是个水.... 题目还原 Two Sum Given an array of integers, find two numbers such that they add up to a specific target number. The fu

2016/1/12 第一题 输出 i 出现次数 第二题 用for循环和if条件句去除字符串中空格 第三题不用endwith 实现尾端字符查询

1 import java.util.Scanner; 2 3 4 public class Number { 5 6 private static Object i; 7 8 /* 9 *第一题 mingrikejijavabu中字符“i” 出现了几次,并将结果输出*/ 10 public static void main(String[] args) { 11 12 String r ="imingrikejijavabi"; 13 14 15 //第一种 截取 16 int a=