【XJOI-NOIP16提高模拟训练9】题解。
2016-07-19 21:06
363 查看
http://www.hzxjhs.com:83/contest/55
说实话这次比赛真的很水。。然而我只拿了140分,面壁反思。
第一题:
发现数位和sum最大就是9*18,k最大1000,那么sum*k最大不过2*10^5,若能被x整除,则x也不超过200000,暴力即可。
不知道学军OIlonglong用%I64d还是%lld输入,用了%I64d爆零。。改成lld就AC了。
第二题
原本用了矩阵乘法来表示i到j走2^k步有多少种方案,方案数>=1就建一条边,最后跑最短路。。超时,50分。
然后发现自己真的好傻逼。。
直接看代码吧。就是一个简单DP,c[i][j][k]表示i到j走2^k步是否可以,d[i][j]表示i到j最少时间。
if d[i][l][k-1]==1 && d[l][j][k-1]==1 --> d[i][j][k]=1
第三题
直接递归。
作死用了树状数组维护前缀和,用个数组就好了吧。。
用树状数组超时90分,改成数组就A了。
说实话这次比赛真的很水。。然而我只拿了140分,面壁反思。
第一题:
发现数位和sum最大就是9*18,k最大1000,那么sum*k最大不过2*10^5,若能被x整除,则x也不超过200000,暴力即可。
不知道学军OIlonglong用%I64d还是%lld输入,用了%I64d爆零。。改成lld就AC了。
#include<cstdio> #include<cstdlib> #include<cstring> #include<iostream> #include<queue> using namespace std; typedef long long LL; int main() { freopen("a.in","r",stdin); freopen("a.out","w",stdout); int T; scanf("%d",&T); while(T--) { LL l,r; int k,ans=0; scanf("%lld%lld%d",&l,&r,&k); for(int i=1;i<=200000;i++) { if(i>r || i<l) continue; int sum=0,x=i; while(x) { sum+=x%10; x/=10; } if((sum*k%i)==0) ans++; } printf("%d\n",ans); } return 0; }
第二题
原本用了矩阵乘法来表示i到j走2^k步有多少种方案,方案数>=1就建一条边,最后跑最短路。。超时,50分。
然后发现自己真的好傻逼。。
直接看代码吧。就是一个简单DP,c[i][j][k]表示i到j走2^k步是否可以,d[i][j]表示i到j最少时间。
if d[i][l][k-1]==1 && d[l][j][k-1]==1 --> d[i][j][k]=1
#include<cstdio> #include<cstdlib> #include<cstring> #include<iostream> #include<queue> using namespace std; typedef long long LL; const int N=60,M=11000; int n,m,d ; bool c [70]; int minn(int x,int y){return x<y ? x:y;} int main() { freopen("a.in","r",stdin); freopen("a.out","w",stdout); scanf("%d%d",&n,&m); memset(c,0,sizeof(c)); memset(d,63,sizeof(d)); for(int i=1;i<=m;i++) { int x,y; scanf("%d%d",&x,&y); d[x][y]=1; c[x][y][0]=1; } for(int k=1;k<=64;k++) for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) for(int l=1;l<=n;l++) { if(c[i][l][k-1] && c[l][j][k-1]) { d[i][j]=1; c[i][j][k]=1; } } for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) for(int l=1;l<=n;l++) { d[i][j]=minn(d[i][j],d[i][l]+d[l][j]); } printf("%d\n",d[1] ); return 0; }
第三题
直接递归。
作死用了树状数组维护前缀和,用个数组就好了吧。。
用树状数组超时90分,改成数组就A了。
#include<cstdio> #include<cstdlib> #include<cstring> #include<iostream> #include<queue> using namespace std; const int N=1100; char s ; int n,c ,d [2]; int lowbit(int x){return x&(-x);} void add(int x,int d){ for(int i=x;i<=n;i+=lowbit(i)) c[i]+=d; } int getsum(int x){ int ans=0; for(int i=x;i>=1;i-=lowbit(i)) ans+=c[i]; return ans; } bool check(int l,int r,int tmp) { if(d[l][r][tmp]!=-1) return d[l][r][tmp]; if(l>r) return 0; if((getsum(r)-getsum(l-1))&1) return d[l][r][tmp]=0; if(tmp==0) { if(l==r && s[l]=='0') return d[l][r][tmp]=1; if(s[l]=='1' && s[r]=='1' && check(l+1,r-1,1)) return d[l][r][tmp]=1; return d[l][r][tmp]=0; } else { int t=getsum(l-1); for(int i=l;i<r;i++) { if((getsum(i)-t)&1) {d[l][i][0]=d[i+1][r][0]=0;continue;} if(check(l,i,0) && check(i+1,r,0)) return d[l][r][tmp]=1; } return d[l][r][tmp]=0; } } int main() { freopen("a.in","r",stdin); // freopen("a.out","w",stdout); int T; scanf("%d",&T); while(T--) { scanf("%d",&n); scanf("%s",s+1); memset(c,0,sizeof(c)); memset(d,-1,sizeof(d)); for(int i=1;i<=n;i++) if(s[i]=='1') add(i,1); if(check(1,n,0)) printf("YES\n"); else printf("NO\n"); } return 0; }
相关文章推荐
- wcf的Contract中name的使用
- 安卓之自定义按钮(以及shape详解)
- 2016腾讯android面试题
- MySQL 设置数据按条件查询下的序号
- Spring MVC @PathVariable 特殊字符
- 【C语言】浮点数的上溢下溢
- 抖动文字
- Single Round Match 695
- JNI.h文件浅析
- 基于XMPP协议的及时通讯
- LinearLayout android:divider属性
- vtkActor在Render中移动的方法
- 人生第一场SRM SRM695 Div.2
- MFC显示图片
- 观察者模式I
- android studio jni.h 红色报错
- 基于粒子群算法的最小二乘支持向量机实现多分类(PSO_LSSVM)
- C#值类型和引用类型的深入理解
- C#值类型和引用类型的深入理解
- C#值类型和引用类型的深入理解