长沙学院2021校赛
比赛链接:https://ac.nowcoder.com/acm/contest/15332#question
差不多应该做出来的都补了,我可真辣鸡呀!
学过的算法还不能ac,太丢人了。。。
A.小圆前辈去上学
题目
链接:https://ac.nowcoder.com/acm/contest/15332/A
来源:牛客网
题目描述
小圆前辈刚上小学一年级,开学第一天老师就讲了对于小数如何四舍五入成整数。
例如:4.78四舍五入就是5,3.11四舍五入就是3。
现在老师让她回家写个程序, 如何将小数四舍五入成整数。
输入描述:
给你一个正实数n。
输出描述:
输出一个整数表示四舍五入后的结果。
思路
签到题,long double数存,输出%.Lf(注意long double 的输出格式为%Lf)
代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define pii pair<int,int>
const double PI=acos(-1.0);
const double eps=0.000001;
int main()
{
long double a;
cin>>a;
printf("%.Lf",a);
return 0;
}
B.小圆前辈的素数
翻博客无意间看到这场校赛的博客,顺便回来补一下这道当时的要命题。
题目
链接:https://ac.nowcoder.com/acm/contest/15332/B
来源:牛客网
题目描述
小焰同学由于在大学的时候不学无术,所学的专业知识不足矣她找到一份像样的工作,这让她很苦恼。之后的某一天她发现,中国几乎所有的科技公司都宣布开始造车,所以她觉得以后汽车维修工作这样的人才缺口一定很大,从此她发奋图强,拜师学艺,在一年后的今天当上了一名光荣的汽车维修师傅。今天是小焰同学上班的第一天,她需要修理的是一辆拥有中控异响、刹车失灵、充电异常、地库自燃等等问题的一台TSL汽车。虽然这种车况本应直接报废要求厂家退款的,但是官方说这是车主自身的问题,不予以质保。乐于助人的小焰同学决定帮一帮这位韭菜。经过问题排查后,她得到了汽车的两组电线接头,一组接头个数为 n ,另一组接头个数为 m 。每个接头都有一个数值显示,她需要将两边的接头每边选择一个进行对接,对接之后两边的数值会进行相加,如果结果为质数的话证明接对了,否则就接错了。如果仅仅是为了接对,她自己就可以解决了,但是好学的她想要知道有多少种正确的对接方式,不学无术的她因为以前训练不饱和做不来,所以请你帮帮她。
输入描述:
第一行输入一个整数t,代表样例组数。 (t ≤ 5)
对于每一组样例中:
第一行输入两个整数 n m (1≤ n, m ≤ 100000)第二行输入 n 个整数表示一边的接头示数
第三行输入 m 个整数表示另一边的接头示数
示数的范围 [1, 100000]
输出描述:
输出一个整数,表示答案。
思路
几个月再看,真是个板的不能再板的题啊!还得是龚神的教育题!
将两组接头示数出现次数存起来,
一波fft卷积操作得到两组接头示数相接之后得到的数出现的个数,
线性筛预处理两倍示数值域内的素数(相接即相加,值域翻倍)
遍历累加满足条件的数出现的个数即可。
别看代码看起来很吓人,会了之后全是板子(滑稽)
CODE
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=3e5+7;
const double eps=1e-6;
const double PI=acos(-1.0);
struct hs
{
double r,i;
hs(double _r = 0,double _i = 0)
{
r = _r; i = _i;
}
hs operator +(const hs &b)
{
return hs(r+b.r,i+b.i);
}
hs operator -(const hs &b)
{
return hs(r-b.r,i-b.i);
}
hs operator *(const hs &b)
{
return hs(r*b.r-i*b.i,r*b.i+i*b.r);
}
};
void change(hs y[],ll len)
{
ll i,j,k;
for(i = 1, j = len/2;i < len-1;i++)
{
if(i < j)swap(y[i],y[j]);
k = len/2;
while( j >= k)
{
j -= k;
k /= 2;
}
if(j < k)j += k;
}
}
void fft(hs y[],ll len,ll on)
{
change(y,len);
for(ll h = 2;h <= len;h <<= 1)
{
hs wn(cos(-on*2*PI/h),sin(-on*2*PI/h));
for(ll j = 0;j < len;j += h)
{
hs w(1,0);
for(ll k = j;k < j+h/2;k++)
{
hs u = y[k];
hs t = w*y[k+h/2];
y[k] = u+t;
y[k+h/2] = u-t;
w = w*wn;
}
}
}
if(on == -1)
for(ll i = 0;i < len;i++)
y[i].r /= len;
}
ll a[N],b[N];
hs x1[N],x2[N];
ll sum[N];
ll num1[N],num2[N];
#define maxn 300007
int prime[maxn+7];
int vis[maxn+7];
void shai()
{
for(int i=2;i<=maxn;i++)
{
if(!vis[i])
{
prime[++prime[0]]=i;
}
for(int j=1;j<=prime[0]&&i*prime[j]<=maxn;j++)
{
vis[i*prime[j]]=1;
if(i%prime[j]==0)
{
break;
}
}
}
}
int main()
{
ios::sync_with_stdio(0);
int t;
cin>>t;
shai();
while(t--)
{
memset(num1,0,sizeof num1);
memset(num2,0,sizeof num2);
int n,m;
cin>>n>>m;
for(int i=0;i<n;i++)
{
cin>>a[i];
num1[a[i]]++;
}
for(int i=0;i<m;i++)
{
cin>>b[i];
num2[b[i]]++;
}
sort(a,a+n);
sort(b,b+m);
int len=1;
int len1=a[n-1]+1;
int len2=b[m-1]+1;
while(len<len1*2||len<len2*2) len*=2;
for(ll i=0;i<len1;i++)
{
x1[i]=hs(num1[i],0);
}
for(ll i=len1;i<len;i++)
{
x1[i]=hs(0,0);
}
for(ll i=0;i<len2;i++)
{
x2[i]=hs(num2[i],0);
}
for(ll i=len2;i<len;i++)
{
x2[i]=hs(0,0);
}
fft(x1,len,1);
fft(x2,len,1);
for(int i=0;i<len;i++)
{
x1[i]=x1[i]*x2[i];
}
fft(x1,len,-1);
for(ll i = 0;i < len;i++)
num1[i] = (ll)(x1[i].r+0.5);
len=a[n-1]+b[m-1];
ll ans=0;
for(int i=2;i<=len;i++)
{
if(!vis[i])
{
ans+=num1[i];
//cout<<"i="<<i<<' '<<"num1[i]="<<num1[i]<<endl;
}
}
cout<<ans<<endl;
}
return 0;
}
C.小圆前辈去爬山
待补
D.小圆前辈的魔法
题目
链接:https://ac.nowcoder.com/acm/contest/15332/D
来源:牛客网
题目描述
小焰同学很害怕虫子,每次看到会飞的昆虫也会跟着飞起来,为此小圆前辈就决定用魔法在寝室里面划定一个区域,让这个区域保持一个无虫的状态,小圆前辈施法过程是这样的:悬停在俯视图为三角形的寝室上空,画上一条边界经过寝室,将寝室分为两个部分,这样较小的区域就会成为一个没有任何虫子的区域,因为小圆前辈的室友更多是喜欢昆虫的。小圆前辈魔法虽然不能划出好友指定大小的区域,但是可以保证的是边界一定会将寝室划分成两个面积大于0的区域。现在请你计算最终小圆前辈能分出多大的区域给好友。
输入描述:
前三行每行两个整型数,代表三角形寝室的坐标
第四行四个整型数,代表边界的坐标
输出描述:
输出一行浮点数,代表小圆前辈好友得到的无虫区域面积
输出与答案误差不超过 1e-6 视为正确答案
思路
一道不算太复杂的几何题,有板子就能做,通过率误我!
总共就六种状态,分别过三个点,或者分别与两条边相交。
判断直线过顶点——叉积为0(如果是判断点在线段上还需要判断x,y在不在两个端点的中间)
判断与哪两条边相交——利用叉积的性质,判断哪两个点在同一边,即可知其两条对边与直线相交
三角形面积——叉积/2.0 的绝对值
代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define N 200007
#define MAXN 110
#define pii pair<int,int>
const double PI=acos(-1.0);
const double eps=0.000001;
#define mod 1000000007;
struct Point
{
double x,y;
Point(){}
Point(double xx,double yy){
x=xx,y=yy;
}
};
struct Line {
Point a, b;
Line(Point aa,Point bb){
a=aa,b=bb;
}
};
double Cross(Point p1,Point p2,Point p3){
return (p2.x-p1.x)*(p3.y-p1.y)-(p2.y-p1.y)*(p3.x-p1.x);
}
double dot_mul(Point p1,Point p2,Point p0){
return (p1.x-p0.x) * (p2.y-p0.y) - (p2.x-p0.x) * (p1.y-p0.y);
}
double Dis(Point A, Point B){
return sqrt((A.x-B.x)*(A.x-B.x) + (A.y-B.y)*(A.y-B.y));
}
bool dot_in_online(Point a,Line b)
{
if(fabs(dot_mul(a,b.a,b.b))<eps)
return 1;
return 0;
}
Point GetLineIntersection(Line u,Line v) {
Point ret = u.a;
double t = ((u.a.x-v.a.x) * (v.a.y-v.b.y) - (u.a.y-v.a.y) * (v.a.x-v.b.x)) / ((u.a.x-u.b.x) * (v.a.y-v.b.y) - (u.a.y-u.b.y) * (v.a.x-v.b.x));
ret.x += (u.b.x - u.a.x) * t;
ret.y += (u.b.y - u.a.y) * t;
return ret;
}
Point operator - (Point A,Point B){
return Point(A.x-B.x, A.y-B.y);
}
Point operator + (Point A, Point B){
return Point(A.x+B.x, A.y+B.y);
}
Point operator * (Point A, double p){
return Point(A.x*p, A.y*p);
}
bool operator == (Point A, Point B){
return (A.x-B.x) == 0 && (A.y-B.y) == 0;
}
int main()
{
Point a,b,c,d,e;
int x,y;
cin>>x>>y;
a=Point(x,y);
cin>>x>>y;
b=Point(x,y);
cin>>x>>y;
c=Point(x,y);
double mj=fabs(Cross(a,b,c)/2.0);
//cout<<mj<<endl;
cin>>x>>y;
d=Point(x,y);
cin>>x>>y;
e=Point(x,y);
Line l=Line(d,e);
if(dot_in_online(a,l))//过a点
{
Point f=GetLineIntersection(l,Line(b,c));
double mjj=fabs(Cross(f,a,c)/2.0);
//cout<<mjj<<endl;
printf("%.10lf\n",min(mj-mjj,mjj));
}
else if(dot_in_online(b,l))//过b点
{
Point f=GetLineIntersection(l,Line(a,c));
double mjj=fabs(Cross(f,b,c)/2.0);
printf("%.10lf\n",min(mj-mjj,mjj));
}
else if(dot_in_online(c,l))//过c点
{
Point f=GetLineIntersection(l,Line(a,b));
double mjj=fabs(Cross(f,a,c)/2.0);
printf("%.10lf\n",min(mj-mjj,mjj));
}
else
{
double mmj;
if(Cross(a,l.a, l.b)*Cross(b,l.a, l.b) > eps)//过a,b边
{
Point xx1 = GetLineIntersection(l, Line(a,c));
Point xx2 = GetLineIntersection(l, Line(b,c));
mmj = fabs(Cross(xx1, xx2, c)/2.0);
}
else if(Cross(c,l.a, l.b)*Cross(b,l.a, l.b) > eps)过c,b边
{
Point xx1 = GetLineIntersection(l, Line(a,c));
Point xx2 = GetLineIntersection(l, Line(a,b));
mmj = fabs(Cross(xx1, xx2, a)/2.0);
}
else if(Cross(a,l.a, l.b)*Cross(c,l.a, l.b) > eps)过a,c边
{
Point xx1 = GetLineIntersection(l, Line(a,b));
Point xx2 = GetLineIntersection(l, Line(b,c));
mmj = fabs(Cross(xx1, xx2, b)/2.0);
}
printf("%.10lf\n",min(mj-mmj,mmj));
}
return 0;
}
E.小圆前辈的排列组合
题目
链接:https://ac.nowcoder.com/acm/contest/15332/E
来源:牛客网
题目描述
小焰同学是小圆前辈的好朋友,她已经在CCSU生活三年了,别看她现在是在ACM实验室,其实在之前她一直忙于各种社团与班级团建活动之中,还在兼顾学习成绩与竞赛强度的她有一些力不从心,尤其是大一的时候因为社团的节目排练还占用了她大部分时间,甚至影响了正常作息,让她在接下来的大学生活一直处于阴影之中。作为她的室友因为长期收到这样的负面情绪而苦不堪言。所以为了让她训练饱和,想要帮她在之后的日子中去除那些琐碎的杂事,只挑有意义的事情让她做,现在我们把所有的事件比作一个长度为 n 的的字符串,每一件事情是一个字符。她在第合数个事件中想要划水看番打游戏,所以你只能从素数事件中挑选事件来让她做,其中如果在所有挑选的事件中可以重新排列组合成为“ CCSU ” 的话,证明她做的事情是有意义的,那么请问在这一系列的事情中她是否可以做有意义的事呢,可以的话输出 “Yes”,否则输出 “No”。(字符串从一开始)
输入描述:
仅包含一行字符串 s
每个字符可能为数字或者大小写字母
输出描述:
如果小焰同学可以做有意义的事情
输出 “Yes”
否则输出 “No”
(不带引号)
思路
筛选出来素数(埃氏筛表示完全能担此重任!),将素数位出现的’C’,‘S’,'U’的数量存下来,判断是否能组成“CCSU”即可。
代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define pii pair<int,int>
const double PI=acos(-1.0);
const double eps=0.000001;
int vis[1000007];
void init()
{
vis[1]=1;
for(int i=2;i<=1000000;i++)
{
if(!vis[i])
for(int j=i+i;j<=1000000;j+=i)
{
vis[j]=1;
}
}
}
int a[5];
int main()
{
init();
string s;
cin>>s;
int si=s.size();
for(int i=0;i<si;i++)
{
if(!vis[i+1])
{
if(s[i]=='C')
{
a[1]++;
}
if(s[i]=='S')
{
a[2]++;
}
if(s[i]=='U')
{
a[3]++;
}
}
}
if(a[1]>=2&&a[2]>=1&&a[3]>=1)
printf("Yes\n");
else
printf("No\n");
return 0;
}
F.小圆前辈的数组Ⅱ
题目
链接:https://ac.nowcoder.com/acm/contest/15332/F
来源:牛客网
题目描述
在你的帮助下,小圆前辈成功破译了这个长为n的数组。原来这个数组是小焰同学上周送给她的,并安排小圆前辈帮她算出数组中的最长完美子序列的长度,可是粗心的小圆前辈忘记了。小圆前辈现在再一个一个找已经来不及了,于是便求助于你,你能帮她算出最长完美子序列的长度吗?
我们定义一个序列是完美的:对于所有的1≤i<n1 \le i < n1≤i<n,满足b[i]不是b[i + 1]的因数。
子序列的定义:a是 b的子序列, 当且仅当可以从b中删除一些元素得到a。
输入描述:
第一行只有三个整数n。第一行共n个整数a[1]~a[n]。
输出描述:
一个整形数表示答案。
思路
涛哥一番点拨,我悟了!赞美涛哥!
还是当最长上升序列的变式来做,我就认为是贪心,涛哥说不是那就不是吧毕竟我是个菜鸡┭┮﹏┭┮
最先想到的还是两层for循环,dp[i]=max(dp[i],dp[j]+1),不出意料的超时。
做这题时想过去记录最大的dp[j]值,但因为可能a[j]是a[i]的因子,无奈放弃这一思路。
但是看到涛哥用了个set优化,不禁感叹涛哥是TN是个天才。
具体优化思路就是
1、记录不同a[i]值所在位置的dp值,不断往后遍历,如果出现相同的a[i]值如果所在dp值更大就将其更新。(因为相同值的话我肯定从最大dp值的位置跳到当前位置)
2、第二层for循环如果从第i个遍历到最后一个会超时,但使用set排序后,从dp值最大的位置往dp值最小的位置遍历就可以有效的减少复杂度。同时因为给定数据最大为1e5,所以最多因子的情况也就一百来个,遍历不了多少次,运算次数至少缩小几十倍。
代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define pii pair<int,int>
const double PI=acos(-1.0);
const double eps=0.000001;
#define mod 998244353723;
int a[100007];
int dp[100007],ma[100007];
set<pii,greater<pii>>s;
int ans=0;
int main()
{
int n;
cin>>n;
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
}
for(int i=1;i<=n;i++)
{
dp[i]=1;
for(auto it: s)//因为给定数据最大1e5,所以最多因子的情况也就一百来个,所以遍历不了多少次!!!set妙极
{
if(a[i]%a[it.second])
{
dp[i]=it.first+1;
break;
}
}
if(!ma[a[i]])//第一次出现a[i]
{
s.insert(pii(dp[i],i));
ma[a[i]]=i;
}
else
{
if(dp[ma[a[i]]]<dp[i])//如果此时的a[i]的dp值大于上一个a[i],就需要更新一下,否则无所谓选择哪一个a[i]
{
s.erase(pii(dp[ma[a[i]]],ma[a[i]]));
s.insert(pii(dp[i],i));
ma[a[i]]=i;
}
}
ans=max(ans,dp[i]);
}
cout<<ans<<endl;
return 0;
}
G.小圆前辈的数组
题目
链接:https://ac.nowcoder.com/acm/contest/15332/G
来源:牛客网
题目描述
小圆前辈最近收到了一个长度为n数组。她怀疑是不怀好意的魔女给她的陷阱,于是她对数组进行了剖析后发现了两个关键的整数k和z,而解读此数组只要算出的所有连续子序列中有多少满足:
1,所有数的和为k的倍数;
2,且其和至少为z;
这个问题难到了小圆前辈,她便把这个问题交给了你,如果你能帮她解决的话,她将奖励你一个Accept。
输入描述:
第一行只有三个整数n,k,z。第一行共n个整数a[1]~a[n]。
输出描述:
一个整形数表示答案。
思路
直接暴力两层循环必然超时。不要想遍历!想都不要想!怎么会优化都不要想!!!血泪史。。。
普及一个实用小技巧,不会二分怎么办,懒得写二分怎么办!upper_bound(),lower_bound()你值得拥有。(赞美涛哥!)
当然,必须是在排好序的数组。(二分当然是在顺序的数组查找,废话)
lower_bound( begin,end,num):从数组的begin位置到end-1位置二分查找第一个大于或等于num的数字,找到返回该数字的地址,不存在则返回end。通过返回的地址减去起始地址begin,得到找到数字在数组中的下标。
upper_bound( begin,end,num):从数组的begin位置到end-1位置二分查找第一个大于num的数字,找到返回该数字的地址,不存在则返回end。通过返回的地址减去起始地址begin,得到找到数字在数组中的下标。
这道题讨论的是一个连续序列的和,那么我们可以在vector内依次存放前缀和(单调递增)
怎么存放前缀和呢?
我们已知的,存在两个k的倍数a,b(a<b),有(b-a)%k==0.
那么我们就可以将前缀和存入下标为前缀和模上k的容器
v[a[i]%k].push_back(a[i]);
接下来我们只要知道从哪一个数开始b-a<z的,就能判断a之前的数都符合题意。
于是,代码↓(注意int会爆数据)
代码
#include<bits/stdc++.h>
using namespace std;
#define IOS ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
double PI=acos(-1.0);
#define ll long long
const double eps=0.000000001;
const ll mod=1e9+7;
ll a[100007];
vector<ll>v[100007];
ll ans=0;
int main()
{
ll n,k,z;
cin>>n>>k>>z;
for(ll i=1;i<=n;i++)
{
scanf("%lld",&a[i]);
a[i]+=a[i-1];
v[a[i]%k].push_back(a[i]);
}
for(ll i=1;i<=n;i++)
{
if(a[i]<z) continue;
if(a[i]%k==0) ans++;
ll p=a[i]-z;
ll tot=a[i]%k;
ll num=upper_bound(v[tot].begin(),v[tot].end(),p)-v[tot].begin();
ans+=num;
}
cout<<ans<<endl;
return 0;
}
H.小圆前辈的博弈
题目
链接:https://ac.nowcoder.com/acm/contest/15332/H
来源:牛客网
题目描述
小圆前辈今天将小焰同学叫来了,她们在玩一个有趣的游戏。小圆前辈有一个长度为n的字符串S,小焰有一个长度为m的字符串T,游戏规则是这样的:首先小圆前辈从S中取出一个子串s,然后小焰从T中取出一个子串t,若s与t相等的话,小圆前辈就输了,否则小焰输。小圆前辈想知道她有多少种必胜的取法,并向你求助,你能告诉她吗?
对于取出的任意的两个子串,只要在原串中位置不同我们就认为是不同的取法。 例如:abab中12的ab与34的ab虽然子串一样,但我们认为是不同的取法。
输入描述:
第一行两个整数n,m分别表示S的长度与T的长度。第二行一个字符串S。第三行一个字符串T。
输出描述:
一个整数表示答案。
思路
这题真给自己蠢哭了,再优化一点就过了,第一次卡常再不想回想
不可我一人感受绝望
都不用map,我就用!!!我就头铁!标准答案好像是用字典树,到时候再写一次。
当然不能简单的使用map,各位如果使用map超时时也可换一个容器unordered_map.具体细节自行百度,反正使用上和map基本没啥区别(只是有一次好像之前用这个里面存pair不进去)
直接往map里存string也是不行的,TLE套餐。需要把string哈希一下,字母有26位,就乘26以上的数字(如27)下一位加的数字就不会影响到上一位了。(友情提示,mod开大一点).
这道题我的实现也很暴力,就是把小焰的字符串的所有字串存进map,再查找小圆前辈的字符串的每个字串就行了。唯一注意的就是!!!一旦小圆前辈的一个字串被检查出小焰没有,代表出现了小焰字符串中没有的字母,那么从该字母遍历到最后一个字母的这些字串小焰都是没有的,可以直接加上跳出循环!!!(就卡这点常气死我)
代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define pii pair<int,int>
const double PI=acos(-1.0);
const double eps=0.000001;
#define mod 998244353723;
int n,m;
unordered_map<ll,int>m1;
int main()
{
cin>>n>>m;
string s,s1;
cin>>s>>s1;
ll num=0;
for(int i=0;i<m;i++)
{
ll p=0;
for(int j=i;j<m;j++)
{
p=(p*27+(s1[j]-'a'+1))%mod;
m1[p]=1;
}
}
for(int i=0;i<n;i++)
{
ll p=0;
for(int j=i;j<n;j++)
{
p=(p*27+(s[j]-'a'+1))%mod;
if(m1[p]!=1)
{
num+=n-j;
break;
}
}
}
cout<<num<<endl;
}
I.小圆前辈的暴力枚举
题目
链接:https://ac.nowcoder.com/acm/contest/15332/I
来源:牛客网
题目描述
小圆前辈家有一个n * m的矩阵,对于矩阵上的每一个格子,你都可以放置一个棋子(易知总共有2n∗m2^{n *m}2n∗m种放置情况)。小圆前辈想知道,在所有放置情况中有多少种情况满足:对于矩阵的每一行且每一列至多只有1个棋子。小圆前辈一想,这不是暴力枚举一下就行了,于是便把问题交给你了,你能求出答案是多少吗。
结果对998244353取模。
输入描述:
一行只有两个整数,n和m。
输出描述:
一个整形数表示答案。
思路
很“洋神”的题!数位DP吧,具体看图
代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define pii pair<int,int>
const double PI=acos(-1.0);
const double eps=0.000001;
#define mod 998244353;
ll f[1007][1007];
ll n,m;
void init()//求组合数
{
for(int i=0;i<=1000;i++)
for(int j=0;j<=i;j++)
{
if(!j) f[i][j]=1;
else f[i][j]=(f[i-1][j]+f[i-1][j-1])%mod;
}
}
ll dp()
{
ll res=0;
ll last=0;
for(int i=n;i>=1;i--)
{
for(int j=0;j<=i-1&&j<m;j++)
{
ll ans=1;
for(int k=m,l=1;l<=j+1&&k>1;k--,l++)
ans=ans*k%mod;
res=(res+f[i-1][j]*ans)%mod;
}
}
return res;
}
int main()
{
init();
cin>>n>>m;
cout<<dp()+1<<endl;//存在一个1都不放的情况所以要+1
}
代码很丑我知道我知道,别骂了别骂了。。。o…orz
J.小圆前辈的异或树
树上启发式到时候再补一下
K.小圆前辈的888
不会