这真的算NOIP?
我还是退役了吧
100+100+20
T1:看似水题,但是超时是很有可能的。
他是判断一个数是不是斐波拉切数列的前n项和
利用牛顿迭代可以一次求出sqrt然后向下取整判断
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<map>
using namespace std;
typedef int INT;
//#define int long long
inline void read(int &x){
x=0;
char ch=getchar();
int f=1;
while(ch<'0'||ch>'9'){
if(ch=='-'){
f=-1;
}
ch=getchar();
}
while(ch>='0'&&ch<='9'){
x=x*10+ch-'0';
ch=getchar();
}
x*=f;
}
int n;
int main(){
freopen("ape.in","r",stdin);
freopen("ape.out","w",stdout);
read(n);
for(register int i=1;i<=n;++i){
int x;
read(x);
int sum=(int)sqrt((x-1)*2);
// cout<<sum<<" ";
if(((sum*(sum+1))/2)==x-1){
puts("1");
}
else{
// cout<<sum<<" "<<((sum*(sum+1))/2)<<" ";
puts("0");
}
}
return 0;
}
T2树形DP:HAOI2015树上染色
一个标准且典型的枚举边的代价
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
using namespace std;
typedef int INT;
#define int long long
inline void read(int &x){
x=0;
char ch=getchar();
int f=1;
while(ch<'0'||ch>'9'){
if(ch=='-'){
f=-1;
}
ch=getchar();
}
while(ch>='0'&&ch<='9'){
x=x*10+ch-'0';
ch=getchar();
}
x*=f;
}
const int N=2100+1;
const int K=2100;
struct Front_star{
int u,v,w,nxt;
}e[N*3];
int cnt=1;
int first[N]={};
void add(int u,int v,int w){
cnt++;
e[cnt].u=u;
e[cnt].v=v;
e[cnt].w=w;
e[cnt].nxt=first[u];
first[u]=cnt;
}
int n,k;
int dp[N][K]={};
int siz[N]={};
int vis[N]={};
int getsiz(int u,int fat){
siz[u]=1;
for(int i=first[u];i;i=e[i].nxt){
int v=e[i].v;
if(v==fat)continue;
siz[u]+=getsiz(v,u);
}
return siz[u];
}
void dfs(int u,int w){
// cout<<u<<'\n';
vis[u]=1;
int siznow=0;
memset(dp[u],-1,sizeof(dp[u]));
dp[u][0]=0;
// cout<<u<<'\n';
for(int i=first[u];i;i=e[i].nxt){
int v=e[i].v;
int w=e[i].w;
// cout<<u<<" "<<v<<" "<<w<<'\n';
if(!vis[v]){
dfs(v,w);
siznow+=siz[v];
for(int j=min(k,siznow);j>=0;j--){
// cout<<u<<" : "<<j<<'\n';
int r=min(j,min(siz[v],k));
for(int k=0;k<=r;k++){
if(dp[u][j-k]!=-1){
dp[u][j]=max(dp[u][j],dp[u][j-k]+dp[v][k]);
}
}
}
}
}
int remain=max(siz[u]+k-n,(int)1);
for(int i=min(k,siz[u]);i>=remain;i--){
int wnow=w*(k-i)*i+w*(n-siz[u]-k+i)*(siz[u]-i);//left k-i right i
dp[u][i]=max(dp[u][i],dp[u][i-1])+wnow;
}
dp[u][0]+=w*(n-siz[u]-k)*(siz[u]);//left k right 0
}
INT main(){
freopen("tree.in","r",stdin);
freopen("tree.out","w",stdout);
//cout<<"here";
read(n);
read(k);
for(int i=1;i<n;i++){
int u,v,w;
read(u);
read(v);
read(w);
add(u,v,w);
add(v,u,w);
}
siz[1]=getsiz(1,0);
dfs(1,0);
cout<<dp[1][k];
// cout<<max(dp[1][k][0],dp[1][k][1]);
return 0;
}
T3神仙题
看见割你需要想到对偶图
但是这有什么用
一个对偶图中的点选不上实际是边成环。
因为对偶图中的点是一个点块。
如果S,T在点块内那么他们都可以连通
否则不行
转化来到了:NOIP2017Day2T1
并查集判环(或者叫做判连通)
暴力代码:
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
using namespace std;
//int idx[N][N]={};
inline void read(int &x){
x=0;
char ch=getchar();
int f=1;
while(ch<'0'||ch>'9'){
if(ch=='-'){
f=-1;
}
ch=getchar();
}
while(ch>='0'&&ch<='9'){
x=x*10+ch-'0';
ch=getchar();
}
x*=f;
}
const int N=51;
struct Front_star{
int u,v,nxt;
}e[N*N*2];
int cnt=1;
int first[N*N]={};
void add(int u,int v){
cnt++;
e[cnt].u=u;
e[cnt].v=v;
e[cnt].nxt=first[u];
first[u]=cnt;
}
int idx[N][N];
int del[N*N][N*N]={};
int vis[N*N];
int n,k;
int lastans=1;
void dfs(int u,int goal){
vis[u]=1;
for(int i=first[u];i;i=e[i].nxt){
int v=e[i].v;
if(vis[v])continue;
if(del[u][v]||del[v][u])continue;
dfs(v,goal);
}
}
void check(int from,int goal){
// cout<<"in"<<'\n';
memset(vis,0,sizeof(vis));
vis[from]=1;
dfs(from,goal);
if(vis[goal]){
lastans=1;
}
else{
lastans=0;
}
if(lastans==1){
puts("TAK");
}
else{
puts("NIE");
}
}
int main(){
freopen("rain.in","r",stdin);
freopen("rain.out","w",stdout);
read(n);
read(k);
int idx_cnt=0;
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
idx[i][j]=++idx_cnt;
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(i>1){
add(idx[i][j],idx[i-1][j]);
}
if(i<n){
add(idx[i][j],idx[i+1][j]);
}
if(j>1){
add(idx[i][j],idx[i][j-1]);
}
if(j<n){
add(idx[i][j],idx[i][j+1]);
}
}
}
// cout<<"------"<<'\n';
for(int i=1;i<=k;i++){
int u1,v1,u2,v2;
char c1[2],c2[2];
scanf("%d%d%s%d%d%s",&u1,&v1,c1,&u2,&v2,c2);
// cout<<"----"<<'\n';
if(lastans==1){
if(c1[0]=='E'){
del[idx[u1][v1]][idx[u1+1][v1]]=1;
check(idx[u1][v1],idx[u1+1][v1]);
}
else{
del[idx[u1][v1]][idx[u1][v1+1]]=1;
check(idx[u1][v1],idx[u1][v1+1]);
}
}
else{
if(c2[0]=='E'){
del[idx[u2][v2]][idx[u2+1][v2]]=1;
check(idx[u2][v2],idx[u2+1][v2]);
}
else{
del[idx[u2][v2]][idx[u2][v2+1]]=1;
check(idx[u2][v2],idx[u2][v2+1]);
}
}
}
// for(int i=1;i<=n*n;i++){
// for(int j=1;j<=n*n;j++){
// cout<<del[i][j]<<" ";
// }
// cout<<'\n';
// }
return 0;
}
std
#include<iostream>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<cstdio>
using namespace std;
int n,k;
int idx[1505][1505]={};
int fa[1505*1505+10]={};
int idx_cnt=1;
int lastans=1;
//inline int getfa(int x){
// int a=x,c;
// while(x!=fa[x])x=fa[x];
// while(x!=(c=fa[a]))fa[a]=x,a=c;
// return x;
//}
int getfa(int x){
if(fa[x]==x)return x;
else return fa[x]=getfa(fa[x]);
}
int main(){
scanf("%d%d",&n,&k);
for(int i=1;i<n;i++){
for(int j=1;j<n;j++){
fa[idx_cnt]=idx[i][j]=idx_cnt++;
}
}
while(k--){
int u1,v1,u2,v2;
char s1[2];
char s2[2];
scanf("%d%d%s%d%d%s",&u1,&v1,s1,&u2,&v2,s2);
if(lastans==0){
u1=u2;
v1=v2;
s1[0]=s2[0];
}
if(s1[0]=='E'){
int a=getfa(idx[u1][v1]);
int b=getfa(idx[u1][v1-1]);
if(lastans=(a!=b))fa[a]=b;
}
else{
int a=getfa(idx[u1][v1]);
int b=getfa(idx[u1-1][v1]);
if(lastans=(a!=b))fa[a]=b;
}
if(lastans==1)puts("TAK");
else puts("NIE");
}
}