给定一个2*n的方格,从左上角开始走有些各自不能走,问能不能一次遍历所有能走的方格。
第一个点可以通过的条件:x同,则y的间距为奇数,x不同,则y的间距为偶数。
不是第一个点,上条件取非
如果最后一行全为教堂也可走完。
#include
#define MAXN 5010
using namespace std;
struct pp
{
int x,y;
}c[MAXN];
int n,m;
bool cmp(pp a,pp b)
{
return a.x<b.x;
}
int main()
{
while(scanf("%d%d",&n,&m)!=EOF)
{
for(int i=0;i<m;i++)
scanf("%d%d",&c[i].y,&c[i].x);
sort(c,c+m,cmp);
bool flag=true;
if(c[0].x%2==0&&c[0].y==2) flag=false;
if(c[0].x%2==1&&c[0].y==1) flag=false;
if(flag)
{
for(int i=m-1;i>=1;)
{
if(c[i-1].x==c[i].x&&c[i].x==n)
n--,i-=2,m-=2;
else if(c[i-1].x==c[i].x&&c[i].x!=n)
{
flag=false;break;
}
else i--;
}
}
if(flag)
{
for(int i=1;i<m;i++)
{
if(c[i-1].y==c[i].y&&(c[i].x-c[i-1].x)%2==0)
{
flag=false;break;
}
else if(c[i-1].y!=c[i].y&&(c[i].x-c[i-1].x)%2==1)
{
flag=false;break;
}
}
}
if(flag) printf("Yes\n");
else printf("No\n");
}
return 0;
}
题意 就是进了100货 进口价1 要分配出口到三个地方 给出三个地方的售价 要求保证每一个地方的销售额都大于100
三个地方的售价是1到1000的实数 保证只给两位小数 给三个地方分配的货物可以以任意精度分配
算法 模拟
解题
由题意推出要确保1/A+1/B+1/C<1,可用1/A+1/B+1/C<1-ε来判别,ε取到2×10-11左右以下即可
#include
using namespace std;
int main()
{
double a,b,c;
long long d,e,f,g;
cin>>a>>b>>c;
if(1/a+1/b+1/c<1-1e-12) cout<<"Yes";
else cout<<"No";
return 0;
}
题意 求N个数于1…R中,他们的最小公倍数为K.
算法 搜索
解题 首先对K分解质因数.先求出1…R中最少的数使得其满足最小公倍数为K,将分解质因数得到的相同因子乘在一起.如K=60=22x3x5,先得到S={3,4,5}.而后再搜索可以把他减小的方案,其中若有两个数乘积小于等于R,可尝试将其乘起来,如R=12时,{3,4,5}可变为{5,12}.从而找到数的最小个数Min.若Min>N,则不能满足条件,若Min
#include
using namespace std;
typedef long long LL;
inline long long read()
{
long long kk=0,f=1;
char cc=getchar();
while(cc<'0'||cc>'9'){if(cc=='-')f=-1;cc=getchar();}
while(cc>='0'&&cc<='9'){kk=(kk<<1)+(kk<<3)+cc-'0';cc=getchar();}
return kk*f;
}
LL k,q,j,i,nv,nm,r,n,Min;
LL a[2100],b[2100],c[2100],d[2100],e[2100];
set<LL>s;
void dfs2(LL d[],LL nm)
{
sort(d+1,d+1+nv);
if ((d[1]*d[2]>r&&nm<Min)||nm==1)
{
Min=nm;
for(LL i=1;i<=nm;i++)
c[i]=d[i];
}
else
{
for(LL i=2;i<=nm&&d[i]*d[1]<=r;i++)
{
for(LL j=1;j<=nm-1;j++)
{
if(j+1==i) e[j]=d[i]*d[1];
else e[j]=d[j+1];
}
dfs2(e,nm-1);
}
}
return;
}
void dfs(LL l,LL v,LL ss)
{
LL temp=0;
c[l]=v;
if(s.size()>=n||ss>r) return;
if (l>=nm) s.insert(ss);
else
for(LL i=0;i<=a[l+1];i++)
{
if(temp) temp=temp*b[l+1];
else temp=1;
dfs(l+1,i,temp*ss);
}
return;
}
int main()
{
n=read();r=read();k=read();
q=0; j=0; i=2;
while(k>1)
{
if(k%i) i++;
else {
k=k/i;
if(i>q)
{
j++;
b[j]=i;
q=i;
c[j]=1;
}
c[j]=i*c[j];
a[j]++;
}
}
sort(c+1,c+1+j);
if(c[j]>r) {
cout<<"-1";
return 0;
}
nm=j; Min=j;
dfs2(c,j);
if(Min>n) {
cout<<"-1";
return 0;
}
for(LL i=1;i<=Min;i++)
s.insert(c[i]);
LL temp=0;
nm=j;
for(LL i=0;i<=a[1];i++)
{
if(temp) temp=temp*b[1];
else temp=1;
dfs(1,i,temp);
}
if(s.size()<n)
{
cout<<"-1";
return 0;
}
for()
return 0;
}
两个人比赛射箭,M为0分,x为10分,110为110分
先看分数,分多的赢,如果一样,看10与x,多的赢,如果依然一样,看x多的赢,再一样shoot-off
#include
#define NMAX 0x7fffffff
using namespace std;
typedef long long LL;
inline long long read()
{
long long kk=0,f=1;
char cc=getchar();
while(cc<'0'||cc>'9'){if(cc=='-')f=-1;cc=getchar();}
while(cc>='0'&&cc<='9'){kk=(kk<<1)+(kk<<3)+cc-'0';cc=getchar();}
return kk*f;
}
int main()
{
int n=read();LL sc=0,shi=0,pl=0;
for(int i=1;i<=n;++i)
{
char cc=getchar();
while(cc=='\n')cc=getchar();
if(cc=='1'&&getchar()=='0'){shi++;sc+=10;}
else if(cc=='X'){shi++;pl++;sc+=10;}
else if(cc=='M');
else sc+=cc-'0';
}
for(int i=1;i<=n;++i)
{
char cc=getchar();
while(cc=='\n')cc=getchar();
if(cc=='1'&&getchar()=='0'){shi--;sc-=10;}
else if(cc=='X'){shi--;pl--;sc-=10;}
else if(cc=='M');
else sc-=cc-'0';
}
if(sc>0)printf("Yuju");
else if(sc<0)printf("Yerin");
else
{
if(shi>0)printf("Yuju");
else if(shi<0)printf("Yerin");
else
{
if(pl>0)printf("Yuju");
else if(pl<0)printf("Yerin");
else printf("Shoot-off");
}
}
}
看到这题第一个想法是看能不能还原成原来的树,可是当n越大,这两种树区别似乎越小,不太好处理。这题的关键在于概率。因为每次增加的节点是等概率的,所以应该根据某种特性判断树的形状,用某一个值作为判断初始状态的标准。
可以想到,如果将某一条边切开,节点相对多的那一边获得新节点的概率更大,良性循环最后的状态更可能是相对大的那一个。
如果将每一条边都这么处理,可以看出,L的平均差异大于R(因为L每次都是1比9,R则是1:9,2:8,3:7…这样子)
这种差异将导致,最后的结果L更倾向于差异大的树,R则倾向于差异小的树。所以可以根据最后的差异来判断,他起源的更可能是那种。如何表示差异的大小呢,可以想到几种平均值,显然,想要将差异最大化的体现可以选择平方平均数(顺便把开方取平均的过程去掉,这样差异更明显,这是一种解法)
贴一波大佬题解
题意大概是,初始有1棵固定10个点的树,分图上两个类型,菊花或者链,之后对这棵树重复990次加点操作,每次加的点,都等概率地连接到已有的节点。给你最后无标号的1000个点的树的结构,让你判断初始是菊花还是链,至多1000组,95%正确率算对。
抠了一下链连出菊花或者菊花连出链的概率,990次连完之后很容易两者都有。
题解是这么写的。
https://lscct.com/challenge/2016solution.pdf
挺抽象的,前置知识Polya urn model,意思大概是初始袋子里有一些蓝球和红球,每次随机摸出1个,然后放回2个同样的球,会造成原先就多的颜色越来越多。
在这题里的体现是,对于每一条边,看他左右两块子树的大小,比如大的那块的点的代表蓝球,小的那块的点代表红球,就能套上这个model,随机选点相当于拿球。经过990次加点之后,这两块的大小差距会被放大,越来越不平衡。初始菊花图所有的边都是极度不平衡的,初始链图的边更平衡一点,我们需要权衡最终的图的平衡度来区分。题解没说具体做法,参考了别人的度量方式,一棵树的平衡度=所有子树的平衡度之和+(该树size * (n - 该树size))²。越平衡的树,就有更多的size更接近n/2,平衡度就更大,因为题面说了标号是随机打乱的,任意取一个树根即可。
代码是错的,做了两天也没能改正确,希望有大佬可以帮忙改正
#include
using namespace std;
typedef long long LL;
inline long long read()
{
long long kk=0,f=1;
char cc=getchar();
while(cc<'0'||cc>'9'){if(cc=='-')f=-1;cc=getchar();}
while(cc>='0'&&cc<='9'){kk=(kk<<1)+(kk<<3)+cc-'0';cc=getchar();}
return kk*f;
}
list<int> k[1111];LL ru[1111],chu[1111],ti=0,num[1111];LL g1,g2,pj,t,n;
void add(int a,int b)
{
k[a].push_back(b);k[b].push_back(a);
}
bool vis[1111];LL ans[1111];
void dfs(int x,int fa)
{
ru[x]=++ti;
num[ti]=x;list<int>::iterator it;
for(it=k[x].begin();it!=k[x].end();++it)
{
if(*it!=fa)dfs(*it,x);
}
chu[x]=ti;
}
void phd(int x,int fa)
{
list<int>::iterator it;int si=chu[x]-ru[x];
ans[x]=si*si*(n-si)*(n-si);
for(it=k[x].begin();it!=k[x].end();++it)
{
if(*it==fa)continue;
phd(*it,x);
ans[x]+=ans[*it];
}
}
int main()
{
t=read();n=read();
for(int i=1;i<=n-1;++i)
{
g1+=(n-i)*i*i*(n-i);
g2+=(n-1)*(n-1);
}
pj=g1/2+g2/2;
while(t--)
{
for(int i=0;i<=n;++i)k[i].clear();
for(int i=1;i<=n-1;++i)
{
add(i,read());
}
list<int>::iterator it;
dfs(0,-1);
phd(0,-1);
if(ans[0]>pj)printf("R\n");
else printf("L\n");
}
}
输入一个日期问之后的2048天内有几个纪念日。
纪念日包括,100天纪念日,两个人的生日,周年纪念日
遍历一遍判断每一天是不是纪念日即可。核心是处理怎么从“今天”进入“明天”。
注意点有:
1.日期达到上限时日期归一,月份加一,月份达到上限时月份归一,年份加一。
2.注意闰二月,特别处理。
#include
#define NMAX 0x7fffffff
using namespace std;
typedef long long LL;
inline long long read()
{
long long kk=0,f=1;
char cc=getchar();
while(cc<'0'||cc>'9'){if(cc=='-')f=-1;cc=getchar();}
while(cc>='0'&&cc<='9'){kk=(kk<<1)+(kk<<3)+cc-'0';cc=getchar();}
return kk*f;
}
int sday,smon,syear,bday,bmon,gday,gmon;int cm[13]={0,31,28,31,30,31,30,31,31,30,31,30,31};
bool check(int d,int m)
{
if(d==sday&&m==smon)return 1;
if(d==bday&&m==bmon)return 1;
if(d==gday&&m==gmon)return 1;
return 0;
}
void doit(int &d,int &m,int &y)
{
bool flag=0;
if(y%4==0)flag=1;if(y%100==0)flag=0;if(y%400==0)flag=1;//flag判断是不是闰年
d++;
if(m==2&&flag)//闰年的二月有29天
{
if(cm[m]+1<d)
{
m++;d=1;
}
}
else if(cm[m]<d)
{
m++;d=1;
}
if(m==13)m=1,y++;
}
int main()
{
int day=read(),mon=read(),year=read();int spe=0;
sday=day;smon=mon;syear=year;
bday=read();bmon=read();gday=read();gmon=read();
for(int i=1;i<=2048;++i)
{
doit(day,mon,year);
if(check(day,mon)||i%100==0)spe++;
}
cout<<spe;
}