- 分享
- @ 2015-10-04 22:50:14
因为有人吐槽...(事实上确实很难看的格式
而且我不太会搞好的效果,所以就链到其它blog上辣
http://zhouzixuan.blog.uoj.ac/blog/810
求轻D
4 条评论
- 
  冲啊小笼包 LV 9 @ 2015-10-14 18:17:02哇,这道题原来这么写,谢谢!我懂了! 
- 
  @ 2015-10-06 17:11:59登录 
 注册
 UOJ Logo zhouzixuan的博客
 zhouzixuan
 日志
 关于我
 UOJ搜索 
 vijos <夜夜的模拟赛之十三岁的梦想> 总结
 2015-10-04 22:20:47 By zhouzixuan
 【写在前面】:
 说实话,打的很不爽
 如果说没想出来就算了,被卡精度什么的从来没有想过
 暴力写错自己弱...说到底还是自己太渣
 如果这样去考noip,就真要跟oi说再见了
 貌似很多人看不懂题解?确实,这题解是有些简单了
 我建议出题人可以放出数据和标程供打架参考(当然这只是个人口胡辣...
 下面进入正题,希望对一些同学有帮助
 T1:夜夜的NOIP之旅:【题目大意】: 
 求1!+2!+...+n!对m取模后的答案
 n<=10^18 m<=1000000
 【题目解法】:
 很显然如果i>=m,那么i!一定是m的倍数,那么模m就等于0
 所以令n=min(n,m),暴力即可
 当然你可以打表找规律,会发现如果某一次得到i!=0那么以后的阶乘模m都等于0
 然后复杂度就是O(M)
 T2:夜夜的数据加强【题目大意】: 
 a[i]=X%i X=(X*A+B)%C
 给出n个a[i]和C,求出所有合法的X A B是的可以生成给定的a[i]
 C<=400 N<=10^5
 【题目解法】:
 至今没有看懂题解在说什么...
 我们可以考虑乱搞
 首先当N<=C是考虑暴力枚举X A B,然后判断复杂度O(C^3*N)勉强卡过
 然后我们发现当i>=C时,a[i]=X%i中的%i是废的,因为C<=i,所以X%C的值已经小于i了,所以我们可以发现对于i>C,其实a[i]就是X的值(不需要模i),所以后面的其实是固定的,即我们不用先枚举X,直接枚举A B,然后判断C~N是否符合要求,如果满足再枚举X,判断前C位是否满足。当然这也是变相暴力辣,不过由于在很多情况下某些A B已经不合法了,所以就不用枚举不必要的X了,这样时间会快一点,大概是O(C^2*N)的复杂度
 然后还是TLE了一个点...
 T3:夜夜的旅游计划【题目大意】: 
 给出N个点M条边的无向图
 每个点等概率向相邻的点走,每条边有一个时间权值
 求1-n的期望时间
 【题目解法】:
 很裸的高斯消元辣
 我们令f[i]表示i-n的期望时间,显然f[n]=0
 那么(f[i]+a[i][j])/outo[i]->f[j],其中outo[i]是i的度,即i有多少个选择
 然后由于有环所以就是一堆方程辣,直接暴力高斯消元就好了
 然而没这么简单,因为他有自环,比如
 2 2
 1 1 1
 1 2 1
 这个数据如果直接做的话outo[1]=3,因为1 1 1这条边会对outo[1]贡献为2,但实际上只有1,因此连边的时候特判一下
 然而没这么简单,因为此题卡精度,好吧,把答案加上1e-5
 然后没这么简单,最后一个点还是过不去,认了...难道真要写long double
 T4:夜夜的花裙子【题目大意】: 现在给定N根火柴棒,有多少合法的"A-B=C"可以用恰好N根火柴棒摆出来呢? 
 【题目解法】:
 首先N=N-3辣
 然后我们考虑dp,首先要明确我们可以枚举所有A+B=C,这与题目是等价的
 令f[i][0/1][0/1][0/1]表示用了i根火柴,从低到高考虑,第一个数是否结束,第二个数是否结束,第三个数是否有进位
 明确进位顶多进一位,因此最高位只能是0/1
 我们考虑如果两个数都结束,显然pass掉
 如果两个数都没结束,显然枚举两个数的最高位,然后考虑是否进位
 如果两个数一个没结束,我们枚举那个数的最高位,然后考虑进位
 答案就是f[n][1][1][0]+f[n][1][1][1],因为最后最后可以进位也可以不进位
 终于写完了,下面放代码T1 
 #include <cstdio>
 #include <cstdlib>
 #include <cstring>
 #include <algorithm>
 using namespace std;
 long long n,m,ans;
 inline long long getint()
 {
 long long x=0; char c=getchar(); bool flag=false;
 while ((c!='-')&&((c<'0')||(c>'9'))) c=getchar();
 if (c=='-') flag=true,c=getchar();
 while ((c>='0')&&(c<='9')) x=x*10+(long long)(c-'0'),c=getchar();
 if (flag) return -x; else return x;
 }
 void init()
 {
 n=getint(); m=getint(); ans=0;
 }
 void solve()
 {
 n=min(n,m); long long base=1;
 for (int i=1; i<=n; i++)
 {
 base=base*(long long)i%m;
 ans=(ans+base)%m;
 }
 printf("%I64d\n",ans);
 }
 int main()
 {
 init();
 solve();
 return 0;
 }
 T2#include <cstdio> 
 #include <cstdlib>
 #include <cstring>
 #include <algorithm>
 using namespace std;
 const int N=100005;
 struct node {int X,A,B;} Ans[N];
 int n,fa[N],ans; long long m;
 inline long long getint()
 {
 long long x=0; char c=getchar(); bool flag=false;
 while ((c!='-')&&((c<'0')||(c>'9'))) c=getchar();
 if (c=='-') flag=true,c=getchar();
 while ((c>='0')&&(c<='9')) x=x*10+(long long)(c-'0'),c=getchar();
 if (flag) return -x; else return x;
 }
 void init()
 {
 n=getint()-1; m=getint();
 for (int i=1; i<=n; i++) fa[i]=getint();
 }
 inline bool cmp(const node &a,const node &b)
 {
 if ((a.X==b.X)&&(a.A==b.A)) return a.B<b.B;
 else if (a.X==b.X) return a.A<b.A;
 else return a.X<b.X;
 }
 void solve()
 {
 for (int i=1; i<=n; i++) if ((fa[i]>=i)||(fa[i]>=m)) {printf("Unsuccessful Hack Attempt\n"); return;}
 if (n<=m)
 {
 for (int X=0; X<m; X++)
 for (int A=0; A<m; A++)
 for (long long B=0; B<m; B++)
 {
 long long base=X; bool flag=true;
 for (int i=1; i<=n; i++)
 {
 if (base%i!=fa[i]) {flag=false; break;}
 base=(base*A+B)%m;
 }
 if (flag) Ans[++ans].X=X,Ans[ans].A=A,Ans[ans].B=B;
 }
 }
 else
 {
 for (int A=0; A<m; A++)
 for (long long B=0; B<m; B++)
 {
 long long base=fa[m]; bool flag=true;
 for (int i=m+1; i<=n; i++)
 {
 base=(base*A+B)%m;
 if (base%i!=fa[i]) {flag=false; break;}
 }
 if (!flag) continue;
 for (int X=0; X<m; X++)
 {
 base=X; flag=true;
 for (int i=1; i<=m; i++)
 {
 if (base%i!=fa[i]) {flag=false; break;}
 base=(base*A+B)%m;
 }
 if (flag) Ans[++ans].X=X,Ans[ans].A=A,Ans[ans].B=B;
 }
 }
 }
 if (ans==0) {printf("Unsuccessful Hack Attempt\n"); return;}
 sort(Ans+1,Ans+ans+1,cmp);
 for (int i=1; i<=ans; i++) printf("%d %d %d\n",Ans[i].X,Ans[i].A,Ans[i].B);
 }
 int main()
 {
 init();
 solve();
 return 0;
 }
 T3#include <cstdio> 
 #include <cstdlib>
 #include <cstring>
 #include <algorithm>
 #include <cmath>
 using namespace std;
 const int N=205;
 const int M=N*N;
 const double zero=1e-9;
 struct edge {int x,y;} b[M];
 int n,m; double a[N][N],ans[N],into[N],sum[N];
 inline long long getint()
 {
 long long x=0; char c=getchar(); bool flag=false;
 while ((c!='-')&&((c<'0')||(c>'9'))) c=getchar();
 if (c=='-') flag=true,c=getchar();
 while ((c>='0')&&(c<='9')) x=x*10+(long long)(c-'0'),c=getchar();
 if (flag) return -x; else return x;
 }
 void init()
 {
 n=getint(); m=getint();
 for (int i=1; i<=n; i++) a[i][i]=1.0;
 for (int i=1; i<=m; i++)
 {
 int x=getint(),y=getint(),z=getint();
 into[x]++; if (x!=y) into[y]++;
 sum[x]+=z; if (x!=y) sum[y]+=z;
 b[i].x=x; b[i].y=y;
 }
 for (int i=1; i<=m; i++)
 {
 int x=b[i].x,y=b[i].y;
 a[x][y]-=1.0/into[x];
 if (x!=y) a[y][x]-=1.0/into[y];
 }
 for (int i=1; i<=n-1; i++) a[i][n+1]=sum[i]/into[i];
 for (int i=1; i<=n+1; i++) a[n][i]=0; a[n][n]=1.0; a[n][n+1]=0;
 }
 void Debug()
 {
 for (int i=1; i<=n; i++)
 {
 for (int j=1; j<=n+1; j++) printf("%.5f ",a[i][j]);
 printf("\n");
 }
 printf("\n");
 }
 void solve()
 {
 //Debug();
 int line=1;
 for (int i=1; i<=n; i++,line++)
 {
 int maxline=line;
 for (int j=line+1; j<=n; j++) if (fabs(a[j][i])>fabs(a[maxline][i])) maxline=j;
 for (int j=1; j<=n+1; j++) swap(a[line][j],a[maxline][j]);
 if (fabs(a[line][i])<zero) {line--; continue;}
 for (int j=i+1; j<=n+1; j++) a[line][j]/=a[line][i]; a[line][i]=1.0;
 for (int j=line+1; j<=n; j++)
 {
 for (int k=i+1; k<=n+1; k++) a[j][k]-=a[line][k]*a[j][i];
 a[j][i]=0.0;
 }
 //Debug();
 }
 for (int i=n-1; i>=1; i--)
 {
 double nowans=a[i][n+1];
 for (int j=i+1; j<=n; j++) nowans-=a[i][j]*ans[j];
 ans[i]=nowans/a[i][i];
 }
 //Debug();
 printf("%.1f\n",ans[1]+1e-5);
 }
 int main()
 {
 init();
 solve();
 return 0;
 }
 T4#include <cstdio> 
 #include <cstdlib>
 #include <cstring>
 #include <algorithm>
 using namespace std;
 const int N=505;
 const int num[]={6,2,5,5,4,5,6,3,7,6,8,4,7,7,6,7,8,5,9,8};
 int n,f[N][2][2][2],cases,casesth,ans; long long maxmod;
 inline long long getint()
 {
 long long x=0; char c=getchar(); bool flag=false;
 while ((c!='-')&&((c<'0')||(c>'9'))) c=getchar();
 if (c=='-') flag=true,c=getchar();
 while ((c>='0')&&(c<='9')) x=x*10+(long long)(c-'0'),c=getchar();
 if (flag) return -x; else return x;
 }
 void init()
 {
 n=getint()-3; maxmod=getint(); casesth++;
 memset(f,0,sizeof(f)); f[0][0][0][0]=1;
 }
 inline void updata(int &a,int b)
 {
 long long New=((long long)a+(long long)b);
 if (New>maxmod) New-=maxmod; a=New;
 }
 void solve()
 {
 for (int i=0; i<n; i++)
 for (int j=0; j<=1; j++)
 for (int k=0; k<=1; k++)
 for (int t=0; t<=1; t++)
 {
 if (f[i][j][k][t]==0) continue;
 if ((j==1)&&(k==1)) continue;
 if ((j==1)||(k==1))
 {
 for (int now=0; now<=9; now++)
 {
 int ii=i+num[now]+num[now+t]-num[t]*t;
 int tt=(now+t>=10); if (ii>n) continue;
 updata(f[ii][j][k][tt],f[i][j][k][t]);
 if (now!=0) updata(f[ii][1][1][tt],f[i][j][k][t]);
 }
 }
 else
 {
 for (int now1=0; now1<=9; now1++)
 for (int now2=0; now2<=9; now2++)
 {
 int ii=i+num[now1]+num[now2]+num[now1+now2+t]-num[t]*t;
 int tt=(now1+now2+t>=10); if (ii>n) continue;
 updata(f[ii][j][k][tt],f[i][j][k][t]);
 if (now1!=0) updata(f[ii][1][k][tt],f[i][j][k][t]);
 if (now2!=0) updata(f[ii][j][1][tt],f[i][j][k][t]);
 if ((now1!=0)&&(now2!=0)) updata(f[ii][1][1][tt],f[i][j][k][t]);
 }
 }
 }
 ans=0; updata(ans,f[n][1][1][0]); updata(ans,f[n][1][1][1]);
 printf("Case #%d: %d\n",casesth,ans%maxmod);
 }
 int main()
 {
 cases=getint();
 while (cases--)
 {
 init();
 solve();
 }
 return 0;
 }
 总结 vijos 好评差评[+2]
 评论
 avatar
 ahdoc好评差评[0]
 第三题。既然每一行中每一项都要除以into[x],为何你不每一项都乘上into[x]?
 之后所有系数都是整数了,这样精度就足够了。
 对于整系数的方程组,甚至可以用 辗转相减 去消元。
 2015-10-05 23:20:54回复
 评论回复
 zhouzixuan:貌似就是因为一开始乘上into[x]导致过程量爆了double,然后WA剩20了...
 2015-10-05 23:39:02回复
 zhouzixuan:回复 @zhouzixuan:不介意的话,能不能发一份代码到我的邮箱研究研究
 2015-10-05 23:51:06回复
 zhouzixuan:不介意的话,能不能发一份代码到我的邮箱研究研究
 2015-10-05 23:51:19回复
 发表评论
 可以用@mike来提到mike这个用户,mike会被高亮显示。如果你真的想打“@”这个字符,请用“@@”。内容 
 提交
 中文 EnglishUniversal Online Judge|鄂ICP备14016048号 
 Server time: 2015-10-06 17:09:12
- 
  @ 2015-10-06 13:36:40快去学markdown orz 
- 
  @ 2015-10-05 19:47:12TMD麻烦你把全部全选(Ctrl+A)然后再按Tab键再发 
 不然这个东西看的强迫症好烦
 例如
 #include<cstdio>
 #include<cstring>
 using namespace std;
 int main()
 {
 int a,b;
 scanf("%d%d",&a,&b);
 printf("%d",a+b);
 return 0;
 }
 A+B问题
- 1