这道题拿上以后,就很闷,十几年的送分模拟题,成了数学题,考场上蒙B的我没思路就先拿样例手动模拟了一下,用了半个小时莫名奇妙用小学奥数乱搞推出了ans=a*b-a-b以后明明是正解,直接输出ans即可。
标准证明思路:
https://www.zybang.com/question/000b3c26c0897ade29aecae936715fee.html
(但是
听监考老师说要跑反作弊分析系统,所以对30%和60%的点用循环写了一遍,好像是for (int i=a*b-1;;i–){…}这样的,反正也能过吧。
)时间复杂度O(1)
但是考场上推出来以后我想,按照初赛提高组的样子,不应该这么简单,在看看,于是就又推了一下发现,设他的两种面值为a,b交换使得a< b,设他用的a,b的数量为na,nb那么又有na,nb是两个循环数列,且数列na的循环周期为b,nb的循环周期为a,这样又有ans<=ab,写一个for,当出现循环时即为ans。时间复杂度O(n)。
因为ans< ab所以从ab+50开始倒着往回求余,首次结果!=0时即为ans。时间复杂度O(n)
但是考场上的我怎么敢写呢,因为证明出ans<=ab,用了大暴力,不知道能过多少个测试点(据说是大数据要开ll“五年OI一场空,没开long long见祖宗” )。考完以后想问我考的是NOIP(全国青少年信息学奥林匹克联赛(National Olympiad in Informatics in Provinces,简称NOIP))还是NOM(math)P。
NOIP出题人莫名其妙把第二题搞了一个模拟,跟2008年pj的立体图有异曲同工之妙,不过蒟蒻的我没打,于是直接打了30分保证前二分之一行全是F的数据的代码然后还写了一个若不符合30分数据的特殊性质则输出YES(根据随机测试数据生成的结果看yes比err和no出现概率大的多)不过多组数据理论上是过不了。回来以后看了题解,就是一个模拟。
写到第三题的时候大概是11点左右,当时也感觉到了CCF一般会把dp放在Day1,第二题纯模拟应该不是(就算是蒟蒻也不会),第三题怎么看也看不出来,知道第三题拿不了分随便写了一个SPFA求最短路+DFS,第三题放这么简单的题,明显数据就有诈,但我还是打了,谁让我们山西分数低去年240省一(\手动开心),民间数据据说很弱。
标答:拓扑排序+DP。好像spfa+DP也是可以的。
看完以后只想说NOIP可能真的是不小心把题目给发反了(还记得内两天的解压密码吗)空间坐标系,看了一下数据范围 109 10 9 擦边int,用longlong可以但是 n2 n 2 相加以后保不准要超longlong,最后证明的确会爆,所以我写了一个
ll r;
ll x,y,z;
cin ......;
r*=r;
int ok=0;
ll dist=pow((x1-x2),2)
if(r<=dist)ok=1;
if(ok==0)dist+=pow((y1-y2),2);
//......
//同理不写
if(ok==1)mp[][]=mp[][]=1;
想分流一下结果把if里的r和dist的比较符号写反了,彻底爆炸。D1T1“是五年OI一场空,没开long long见祖宗”这个开了ll都不行还要BigInteger。
一看题,为什么n那么小(<=12),那么多条边,正常思路都是重边,就我一看觉得是稠密图开开心心的写了一个邻接矩阵,心里还想真好写比vector的链表好多了,后来才知道有重边。考前就在说肯定会有DP。因为n<=12,状压DP,网上看到有现成的代码,就直接上了,时间复杂度 O(2n∗n3) O ( 2 n ∗ n 3 )
其实根据状压dp那么多个if的特性肯定是不会爆的,可是我非得头铁,要搞到 O(2n∗n3) O ( 2 n ∗ n 3 ) ,结果搞成了,但是发现错的,然后就不改了。为此浪费了我45分钟时间
有人说最小生成树好像也可以,大数据也貌似可以过。五中有一个考前说要先打一个打最小生成树的模板的还真中了,不过也有人说过不了。
标答:状压dp
别人的代码:
#include
using namespace std;
int bo[5020][22];
int f[5020];
int n;
int edge[22][22];
int m;
int ans=0x7ffffff;
int dfs(int root)
{
memset(bo,0,sizeof(bo));
memset(f,63,sizeof(f));
f[1<<(root)] = 0; //初始化
bo[(1<1;
int N = 1<for(int i=0;i//枚举点的状态
for(int j=0;jif((i&(1<0) //j点能到达
for(int k=0;kif(((i&(1<0)&&(edge[j][k]!=-1))//k点不能到达,且jk之间有边
{
int p = (1<int x = f[i] + bo[i][j] * edge[j][k]; //计算费用,方程
if(f[i+p]>x)
{
f[i+p] = x;
for(int l=0;l1;
}
}
return f[N-1];
}
int main()
{
memset(edge,-1,sizeof(edge));
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
{
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
if(edge[x-1][y-1]>z || edge[x-1][y-1]==-1) //记得直接选权值最小的边就可以了
edge[x-1][y-1]=edge[y-1][x-1]=z; //直接清除重边。
}
for(int i=0;i//以i为出发点。
ans = min(ans,dfs(i));
printf("%d\n",ans);
}
知道第三题做不出来的我直接打了测试点1,2,3,4,5,6,11,12,13,14
不知道要错几个。
正解:splay/树状数组
可以看出近几年NOIP的出题者一直在寻求革新(那你也不能把D1T1搞成小学数学呀),从初赛提高组到普及组到现在的复赛提高组,难度也在波动,我们不能说NOIP怎么样,只能不断去适应他,虽然有很多遗憾的失误,但也没办法了,安心滚回去高考吧,也希望大双语的OI可以从此崛起,双语的同学不是不行,而是缺少一个发现自己的机会,与教学资源。