http://codeforces.com/problemset/problem/404/b
B. Marathon
思路简单,但对于精度处理
注意几点:
1.控制输出0 -- 0.0
2.巧妙应用浮点数取模函数:
因为它们之间存在各种关系,使用dps1=fmod(s1,4*a);每次加上就取模减小,不能让数字增大,累计误差。#include <iostream> #include <cmath> #include <cstdio> using namespace std; int main() { //freopen("cin.txt","r",stdin); double a,d; int n; while(~scanf("%lf%lf",&a,&d)){ scanf("%d",&n); double s1=0.0,s2=0.0; for(int i=1;i<=n;i++){ s1+=d; s1=fmod(s1,4*a); if(s1<=a) printf("%.10lf %.10lf\n",s1,0.0); else if(s1<=2*a) printf("%.10lf %.10lf\n",a,s1-a); else if(s1<=3*a) printf("%.10lf %.10lf\n",a-(s1-2*a),a); else printf("%.10lf %.10lf\n",0.0,a-s1+3*a); } } return 0; }
http://codeforces.com/problemset/problem/404/cC. Restore Graph
看成一棵树,模拟。#include <iostream> #include <cstdio> #include <algorithm> #include <vector> using namespace std; const int N=1e5+10; typedef long long LL; int main() { //freopen("cin.txt","r",stdin); int n,k,a; while(cin>>n>>k){ vector<int> vec[n]; int D=0; for(int i=1;i<=n;i++){ scanf("%d",&a); vec[a].push_back(i); D=max(D,a); } if(vec[0].size()!=1){ puts("-1"); continue; } bool flag=1; for(int i=0;i<D;i++){ if(i==0){ if(vec[i].size()*k+0LL<vec[i+1].size()){ puts("-1"); flag=0; break; } } else { if(vec[i].size()*(k-1LL)<vec[i+1].size()) { //超出int puts("-1"); flag=0; break; } } } if(flag==0)continue; printf("%d\n",n-1); int cnt; //记录一点和高层结点连接的个数 for(int w=0;w<D;w++){ int len=vec[w+1].size(),i=0; if(w==0) cnt=0; else cnt=1; for(int j=0;j<len;) if(cnt<k){ printf("%d %d\n",vec[w][i],vec[w+1][j]); j++; cnt++; } else { cnt=1; //上面已经排除了超过k的情况,接着,高层的点连在同层的其他点上 i++; } } } return 0; }
http://codeforces.com/problemset/problem/404/DD. Minesweeper 1D
第一种思路,完全的从前向后推:
0: 本位置是0
1:本位置是1且左边有雷
2:本位置是1且右边有雷
3:本位置是2
4:本位置是*
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
typedef long long LL;
const int N=1e6+10,mod=1e9+7;
LL dp[N][5];
char str[N];
int main()
{
//freopen("cin.txt","r",stdin);
while(cin>>str){
int len=strlen(str);
memset(dp,0,sizeof(dp));
if(str[0]=='0') dp[0][0]=1; //递推的“头”和“尾”是关键
else if(str[0]=='1') dp[0][2]=1;
else if(str[0]=='*') dp[0][4]=1;
else if(str[0]=='2') {
printf("0\n");
continue;
}
else if(str[0]=='?') {
dp[0][0]=1;
dp[0][2]=1;
dp[0][4]=1;
}
for(int i=1;i<len;i++){
if(str[i]=='0') {
dp[i][0]=dp[i-1][0]+dp[i-1][1];
dp[i][0]%=mod;
}
else if(str[i]=='1'){
dp[i][1]=dp[i-1][4];
dp[i][2]=dp[i-1][0]+dp[i-1][1];
dp[i][2]%=mod;
}
else if(str[i]=='2'){
dp[i][3]=dp[i-1][4];
}
else if(str[i]=='*'){
dp[i][4]=dp[i-1][2]+dp[i-1][3]+dp[i-1][4];
dp[i][4]%=mod;
}
else if(str[i]=='?'){
dp[i][0]=dp[i-1][0]+dp[i-1][1];
dp[i][0]%=mod;
dp[i][1]=dp[i-1][4];
dp[i][2]=dp[i-1][0]+dp[i-1][1];
dp[i][2]%=mod;
dp[i][3]=dp[i-1][4];
dp[i][4]=dp[i-1][2]+dp[i-1][3]+dp[i-1][4];
dp[i][4]%=mod;
}
}
LL ans=dp[len-1][0]+dp[len-1][1]+dp[len-1][4];
ans%=mod;
printf("%I64d\n",ans);
memset(str,0,sizeof(str));
}
return 0;
}
第二种思路:前后关系充分考虑:
0: i is *, i+1 is not *
1: i is *, i+1 is *
2: i is not *, i+1 is not *
3: i is *, i is *
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
typedef long long LL;
const int N=1e6+10,mod=1e9+7;
LL dp[N][4];
char str[N];
int main()
{
//freopen("cin.txt","r",stdin); //where is wrong ?
while(~scanf("%s",str+1)){
int len=strlen(str+1);
memset(dp,0,sizeof(dp));
dp[0][0]=dp[0][1]=1;
for(int i=1;i<len;i++){
if(str[i]=='0'){
dp[i][0]=dp[i-1][0];
}
if(str[i]=='1'){
dp[i][0]=dp[i-1][2];
dp[i][1]=dp[i-1][0];
}
if(str[i]=='2'){
dp[i][1]=dp[i-1][2];
}
if(str[i]=='*'){
dp[i][3]=(dp[i-1][3]+dp[i-1][1])%mod;
dp[i][2]=(dp[i-1][3]+dp[i-1][1])%mod;
}
if(str[i]=='?'){
dp[i][0]=(dp[i-1][2]+dp[i-1][0])%mod;
dp[i][1]=(dp[i-1][2]+dp[i-1][0])%mod;
dp[i][2]=(dp[i-1][3]+dp[i-1][1])%mod;
dp[i][3]=(dp[i-1][3]+dp[i-1][1])%mod;
}
}
LL ans;
if(str[len]=='0') ans=dp[len-1][0];
else if(str[len]=='1') ans=dp[len-1][2];
else if(str[len]=='2') ans=0;
else if(str[len]=='*'){
ans=(dp[len-1][1]+dp[len-1][3])%mod;
}
else {
ans=(dp[len-1][0]+dp[len-1][1]+dp[len-1][2]+dp[len-1][3])%mod;
}
printf("%I64d\n",ans);
memset(str,0,sizeof(str));
}
return 0;
}
但是,,,这两种AC的代码都有漏洞啊,比如:1* 输出了1,应该是0才对。