哈尔滨理工大学2016级新生程序设计全国邀请赛
2016-12-11 18:09
399 查看
题目链接:点我点我(2293-2303)
A 棋盘村
简单dp
dp[1][1]=1
dp[i][j]=dp[i-1][j]+dp[i][j-1]
判掉强盗能到的地方即可
B 修建传送门
首先左传送门肯定放在1位置 不然会多走1到左传送门的距离
所以可以利用双指针 枚举右传送门的位置 进而找出折中点 更新ans即可
C 方方正正
首先行列和不相同肯定不行
其次如果行上的最大值如果大于列的非零值的个数也不行 列同理
D 陈月亮的数学题
我们知道可以将一个数N分解成N=pa11∗pa22∗pa33∗…∗pann,其中Pi为素数。这样N的因子个数为(a1+1)(a2+1)(a3+1)…(ak+1)=∏ki=1(ai+1)。
所以N的所有因子的因子个数为∏ki=1(1+2+3+…+ai+1)=∏ki=1(1+ai+1)(ai+1)2,但这只是S=n1+n2+n3+…+nk的值。
所以,我们可以从1+2+3+…+n=(1+n)n2。
12+22+32+…+n2=(2+n)(1+n)n6
13+23+33+…+n3=((1+n)n2)2中得到启示。
所以最终S=n31+n32+n33+…+n3k的答案为∏ki=1((1+ai+1)(ai+1)2)2
膜一发神犇的题解。。。
E Nine Digits
康拓展开后bfs即可 但是这样会超时
所以可以先处理出原序列能到的地方 然后每次询问查询康拓展开
原来是顺时针 所以预处理时候用逆时针
F Diamond
不会。。。
G FBI Tree
递归处理前缀和即可
H 下雪啦
hash后存到vector里面 然后暴力匹配同一个集合里面的雪花
I 行编辑器
水题 处理个指针就行了
J Another Tree
建树 然后随便找个结点搜 两个点的异或距离为两个点到根节点的异或距离异或起来 根据这个性质dfs搜下去即可
L 小明和字符串
水题。。。
A 棋盘村
简单dp
dp[1][1]=1
dp[i][j]=dp[i-1][j]+dp[i][j-1]
判掉强盗能到的地方即可
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; typedef long long ll; ll vis[25][25]; int main(){ ll t; scanf("%lld",&t); while(t--){ ll i,j,n,m,x,y; memset(vis,0,sizeof(vis)); scanf("%lld%lld%lld%lld",&n,&m,&x,&y); n++; m++; x++; y++; if(x-2>=0&&y-1>=0)vis[x-2][y-1]=-1; if(x-1>=0&&y-2>=0)vis[x-1][y-2]=-1; if(x-2>=0)vis[x-2][y+1]=-1; if(x-1>=0)vis[x-1][y+2]=-1; if(y-2>=0)vis[x+1][y-2]=-1; if(y-1>=0)vis[x+2][y-1]=-1; vis[x+2][y+1]=-1; vis[x+1][y+2]=-1; vis[x][y]=-1; if(vis[1][1]!=-1){ vis[1][1]=1; for(i=1;i<=n;i++){ for(j=1;j<=m;j++){ if(vis[i][j]==-1)continue; if(vis[i-1][j]!=-1)vis[i][j]+=vis[i-1][j]; if(vis[i][j-1]!=-1)vis[i][j]+=vis[i][j-1]; } } } printf("%lld\n",vis [m]); } return 0; }
B 修建传送门
首先左传送门肯定放在1位置 不然会多走1到左传送门的距离
所以可以利用双指针 枚举右传送门的位置 进而找出折中点 更新ans即可
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; typedef long long ll; ll sum[100005]; int main(){ ll t; scanf("%lld",&t); while(t--){ ll n,i,j,x; scanf("%lld",&n); memset(sum,0,sizeof(sum)); for(i=2;i<=n;i++){ scanf("%lld",&x); sum[i]+=sum[i-1]+x; } ll zhe=1,ans=1; for(i=1;i<=60;i++)ans*=2; for(i=2;i<=n;i++){ ll d=min(ans,sum -sum[i]); while(zhe!=n-1&&max(sum[i]-sum[zhe+1],sum[zhe]-sum[1])>max(sum[i]-sum[zhe+2],sum[zhe+1]-sum[1]))zhe++; d=max(sum[zhe]-sum[1],d); d=max(sum[i]-sum[zhe+1],d); ans=min(ans,d); } if(n==1)ans=0; cout<<ans<<endl; } return 0; }
C 方方正正
首先行列和不相同肯定不行
其次如果行上的最大值如果大于列的非零值的个数也不行 列同理
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; typedef long long ll; int row[100005],col[100005]; int main(){ int i,j,r,c; while(scanf("%d%d",&r,&c)!=EOF){ ll rsum=0,csum=0; ll numr,numc,maxc,maxr; maxr=maxc=numr=numc=0; for(i=1;i<=r;i++){ scanf("%d",&row[i]); rsum+=row[i]; if(row[i]>0)numr++; if(row[i]>maxr)maxr=row[i]; } for(i=1;i<=c;i++){ scanf("%d",&col[i]); csum+=col[i]; if(col[i]>0)numc++; if(col[i]>maxc)maxc=col[i]; } int flag=1; if(rsum!=csum)flag=0; if(numc<maxr||numr<maxc)flag=0; if(flag)printf("YES\n"); else printf("NO\n"); } return 0; }
D 陈月亮的数学题
我们知道可以将一个数N分解成N=pa11∗pa22∗pa33∗…∗pann,其中Pi为素数。这样N的因子个数为(a1+1)(a2+1)(a3+1)…(ak+1)=∏ki=1(ai+1)。
所以N的所有因子的因子个数为∏ki=1(1+2+3+…+ai+1)=∏ki=1(1+ai+1)(ai+1)2,但这只是S=n1+n2+n3+…+nk的值。
所以,我们可以从1+2+3+…+n=(1+n)n2。
12+22+32+…+n2=(2+n)(1+n)n6
13+23+33+…+n3=((1+n)n2)2中得到启示。
所以最终S=n31+n32+n33+…+n3k的答案为∏ki=1((1+ai+1)(ai+1)2)2
膜一发神犇的题解。。。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; typedef long long ll; int prime[100005],num[100005],cnt=0; void init(){ for(int i=2;i<=65536;i++){ if(!prime[i])num[++cnt]=i; for(int j=2;j*i<=65536;j++){ prime[j*i]=1; if(!(i%j)) break; } } } int main(){ int t; init(); scanf("%d",&t); while(t--){ int n; scanf("%d",&n); ll ans=1; for(int i=1;i<=cnt;i++){ if(n%num[i]==0){ int s=0; while(n%num[i]==0){ n/=num[i]; s++; } ll temp=(2+s)*(1+s)*(2+s)*(1+s)/4; ans*=temp; } } if(n>1)ans*=9; cout<<ans<<endl; } return 0; }
E Nine Digits
康拓展开后bfs即可 但是这样会超时
所以可以先处理出原序列能到的地方 然后每次询问查询康拓展开
原来是顺时针 所以预处理时候用逆时针
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<deque> using namespace std; deque<int>sp; int fac[] = {1,1,2,6,24,120,720,5040,40320,362880},vis[362999]; int kangtuo(int a[]) { int i,j,t,sum; sum=0; for(i=0;i<9;++i) { t=0; for(j=i+1;j<9;++j) if(a[i]>a[j])sum+=fac[9-i-1]; } return sum+1; } int s[20]; void reverse_kangtuo(int k){ int i,j,t,vst[9]={0}; --k; for(i=0;i<9;i++){ t=k/fac[9-i-1]; for(j=1;j<=9;j++) if(!vst[j]){ if(t==0)break; --t; } s[i]=j; vst[j]=1; k%=fac[9-i-1]; } } int main(){ memset(vis,-1,sizeof(vis)); int m=1; vis[1]=0; int f; sp.push_back(m); while(!sp.empty()){ f=sp.front(); sp.pop_front(); reverse_kangtuo(f); swap(s[3],s[0]); swap(s[4],s[0]); swap(s[1],s[0]); m=kangtuo(s); if(vis[m]==-1){ vis[m]=vis[f]+1; sp.push_back(m); } swap(s[1],s[0]); swap(s[4],s[0]); swap(s[3],s[0]); swap(s[1],s[4]); swap(s[1],s[5]); swap(s[1],s[2]); m=kangtuo(s); if(vis[m]==-1){ vis[m]=vis[f]+1; sp.push_back(m); } swap(s[1],s[2]); swap(s[1],s[5]); swap(s[1],s[4]); swap(s[3],s[6]); swap(s[3],s[7]); swap(s[3],s[4]); m=kangtuo(s); if(vis[m]==-1){ vis[m]=vis[f]+1; sp.push_back(m); } swap(s[3],s[4]); swap(s[3],s[7]); swap(s[3],s[6]); swap(s[4],s[7]); swap(s[4],s[8]); swap(s[4],s[5]); m=kangtuo(s); if(vis[m]==-1){ vis[m]=vis[f]+1; sp.push_back(m); } } while(scanf("%d%d%d%d%d%d%d%d%d",&s[0],&s[1],&s[2],&s[3],&s[4],&s[5],&s[6],&s[7],&s[8])!=EOF){ int f=kangtuo(s); printf("%d\n",vis[f]); } return 0; }
F Diamond
不会。。。
G FBI Tree
递归处理前缀和即可
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; #define maxn 1<<10 int a[maxn+5],sum[maxn+5]; void build(int l,int r){ int p=sum[r]-sum[l-1]; if(l!=r){ int len=r-l+1; if(len%2){ build(l,(r+l)/2-1); build((r+l)/2+1,r); } else{ build(l,(r+l)/2); build((r+l)/2+1,r); } } if(p==0)printf("B"); else if(p==r-l+1)printf("I"); else printf("F"); } int main(){ int t; scanf("%d",&t); while(t--){ int i,n; scanf("%d",&n); int len=1<<n; for(i=1;i<=len;i++){ scanf("%1d",&a[i]); sum[i]=sum[i-1]+a[i]; } build(1,len); printf("\n"); } return 0; }
H 下雪啦
hash后存到vector里面 然后暴力匹配同一个集合里面的雪花
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<vector> using namespace std; vector<int>sp[90005]; const int mod=90001; int snow[1000005][7]; int judge(int a,int b){ for(int i=0;i<6;i++){ if((snow[a][0]==snow[b][i]&& snow[a][1]==snow[b][(i+1)%6]&& snow[a][2]==snow[b][(i+2)%6]&& snow[a][3]==snow[b][(i+3)%6]&& snow[a][4]==snow[b][(i+4)%6]&& snow[a][5]==snow[b][(i+5)%6]) || (snow[a][0]==snow[b][i]&& snow[a][1]==snow[b][(i+5)%6]&& snow[a][2]==snow[b][(i+4)%6]&& snow[a][3]==snow[b][(i+3)%6]&& snow[a][4]==snow[b][(i+2)%6]&& snow[a][5]==snow[b][(i+1)%6])) return true; } return false; } int main(){ int t; scanf("%d",&t); while(t--){ int n,i,j,flag=0; scanf("%d",&n); for(i=1;i<=n;i++){ for(j=0;j<6;j++)scanf("%d",&snow[i][j]); } for(i=0;i<=90000;i++)sp[i].clear(); for(i=1;i<=n;i++){ int sum=0; for(j=0;j<6;j++)sum+=snow[i][j]; sum%=mod; for(j=0;j<sp[sum].size();j++){ if(judge(sp[sum][j],i)){ flag=1; break; } } if(flag)break; sp[sum].push_back(i); } if(flag)printf("Twin snowflakes found.\n"); else printf("No two snowflakes are alike.\n"); } return 0; }
I 行编辑器
水题 处理个指针就行了
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; char s[1000005],ans[1000005]; int main(){ int t; scanf("%d",&t); while(t--){ scanf("%s",s+1); int d=0,i; int len=strlen(s+1); for(i=1;i<=len;i++){ if(s[i]=='#')d=max(0,d-1); else if(s[i]=='@')d=0; else ans[++d]=s[i]; } for(i=1;i<=d;i++)printf("%c",ans[i]); printf("\n"); } return 0; }
J Another Tree
建树 然后随便找个结点搜 两个点的异或距离为两个点到根节点的异或距离异或起来 根据这个性质dfs搜下去即可
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; typedef long long ll; int head[500005],cnt,tree[1000005],k; struct node{ int to,cap,nex; }edge[1000005]; void add(int u,int v,int w){ edge[cnt].to=v; edge[cnt].cap=w; edge[cnt].nex=head[u]; head[u]=cnt++; } ll ans; void dfs(int t,int d,int sum){ ans+=tree[sum^k]; tree[sum]++; for(int i=head[d];~i;i=edge[i].nex){ int v=edge[i].to; if(v!=t){ dfs(d,v,sum^edge[i].cap); } } } int main(){ int t; scanf("%d",&t); while(t--){ memset(head,-1,sizeof(head)); memset(tree,0,sizeof(tree)); cnt=0; int x,y,z,n,i; scanf("%d%d",&n,&k); for(i=1;i<n;i++){ scanf("%d%d%d",&x,&y,&z); x++; y++; add(x,y,z); add(y,x,z); } ans=0; dfs(1,1,0); printf("%lld\n",ans); } return 0; }
L 小明和字符串
水题。。。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; char s[55]; int main(){ int t; scanf("%d",&t); while(t--){ scanf("%s",s+1); int i,j,k,len=strlen(s+1); for(i=1;i<=len;i++){ int now=0; for(j=i+1;j<=len;j++){ if(!(s[j]>='0'&&s[j]<='9'))break; now+=s[j]-'0'; } for(k=1;k<=now+1;k++)printf("%c",s[i]); i=j-1; } printf("\n"); } return 0; }
相关文章推荐
- [教程]phpwind9.0应用开发基础教程
- 初识Sqlite数据库
- arm第十一天(汇编与C混调、异常处理)
- 基于位置的服务
- Hadoop HBase概念学习系列之RowKey设计(二十九)
- MyBatis-自定义数据库厂商ID
- cassandra的写过程
- 【C#】总结一——c#基础
- java基础14(Javaoo9)——集合框架
- 结构体 - 基础
- 学会用各种姿势备份MySQL数据库
- [ZJOI2008]树的统计——树链剖分
- 丑数
- 微信订阅号和服务号再探究竟
- X11 xcb 交叉编译
- 第一行代码(第二版)全书代码下载
- DDS信号产生实验
- bzoj1015星球大战(并查集+离线)
- boost:asio信号量signal_set源码分析及使用
- 如何优雅的选择默认字体(font-family)