这次做出了三道题,三道题都过了,可惜出得太慢了(比赛二十分钟了才开始做).Rating = 1651+41 = 1692. 诶.继续Div 2吧>_<!
A:
就对每层的三个数top,l,r满足
(l != top && r!= top &&l!=7-top && r!=7-top && l+r!=7)条件就是合法的.
#include<iostream>
#include<cstdio>
using namespace std;
int n,top,l,r;
bool flag;
int main()
{
cin >> n;
cin >> top;
flag = 1;
for (int i = 0;i<n;++i)
{
cin>> l >> r;
if (l != top && r!= top && l!=7-top && r!=7-top && l+r!=7)
{
top = 7-top;
} else
{
flag = 0;
}
}
if (flag) cout << "YES" << endl; else
cout << "NO" << endl;
return 0;
}
B:
- F(k, n) = 0, for integer n, 1 ≤ n < k;
- F(k, k) = 1;
- F(k, n) = F(k, n - 1) + F(k, n - 2) + ... + F(k, n - k), for integer n, n > k.
按照这个规则,算出所有小于s的f(k,n).
然后从大到小贪心就可以了.正确性的保证是f(k,n)>f(k,n-1)+f(k,n-2).
#include<iostream>
#include<cstdio>
using namespace std;
int s,k;
long long f[10000];
int cnt = 0;
int Stack[1000];
int tp;
int main()
{
cin >> s >> k;
f[0] = 1;
tp = 0;
while (f[tp]<s)
{
++tp;
f[tp] = 0;
for (int i = 1;i<=k;++i)
if (tp-i>=0)
{
f[tp] += f[tp-i];
} else break;
}
if (f[tp]>s) --tp;
// for (int i = 0;i<=tp;++i) cout << f[i] << endl;
while (s>0 && tp >= 0)
{
if ( s - f[tp] >= 0)
{
s -= f[tp];
Stack[cnt] = f[tp];
++cnt;
}
//cout << s << endl;
--tp;
}
if (cnt == 1)
{
cout << "2" << endl;
cout << "0 "<<Stack[0] << endl;
} else{
cout << cnt << endl;
for (int i = cnt-1;i>0;--i) cout << Stack[i] << " ";
cout << Stack[0] << endl;
}
return 0;
}
C:
用动态规划做,
F[i][0..1]分别使前i组满足题设且最后一段为黑或白的最小改变数.
l f[i][0] = min(f[i][0],f[i-j][1]+n*j-sum[i]+sum[i-j]);
l f[i][1] = min(f[i][1],f[i-j][0]+sum[i]-sum[i-j]);
l sumi表示第前i列的黑格个数.
#include<iostream>
#include<cstdio>
#include<string>
#include<algorithm>
using namespace std;
string ma[1001];
int b[1001],sum[1001];
int f[1001][2];
int n,m,x,y;
int main()
{
cin >> n >> m >> x >> y;
for (int i = 0;i<n;++i) cin >> ma[i];
for (int i = 1;i<=m;++i)
{
b[i] = 0;
for (int j= 0;j<n;++j)
b[i] += (ma[j][i-1] == '#');
sum[i] = sum[i-1]+b[i];
}
f[0][0] = f[0][1] = 0;
for (int i = 1;i<=m;++i) f[i][0] = f[i][1] = 1000000000;
for (int i = 1;i<=m;++i)
{
for (int j = x;j<=y;++j)
if (i-j>=0)
{
f[i][0] = min(f[i][0],f[i-j][1]+n*j-sum[i]+sum[i-j]);
f[i][1] = min(f[i][1],f[i-j][0]+sum[i]-sum[i-j]);
}
}
cout << min(f[m][0],f[m][1]) << endl;
return 0;
}
D:
仍旧是动态规划,
F[i][j][opt]表示头在(I,j)状态为opt(opt用2*(len-1)位来表示蛇的形态,用两位来表示(i-1,i)的方位,方位显然是四个,于是就两位就可以了).
空间复杂度大致是15*15*(1<<16)
转移时每次4次.四个方向.
#include<iostream>
#include<cstdio>
#include<string>
#include<queue>
using namespace std;
string ma[15];
int dp[15][15][1<<16];
int in[15][15];
int dirx[4]={0,1,0,-1};
int diry[4]={1,0,-1,0};
struct NODE
{
int x,y,opt;
};
queue<NODE> que;
int n,m,len,opt,sx,sy,tx,ty;
int mask;
const int inf = 1000000000;
int getDir(int x,int y,int num)
{
for (int i = 0;i<4;++i)
if (x+dirx[i]>=0 && x+dirx[i]<n && y+diry[i]>=0 && y+diry[i]<m
&& ma[x+dirx[i]][y+diry[i]] == '0'+num)
{
return i^2;
}
return 0;
}
int main()
{
cin >> n >> m;
for (int i = 0;i<n;++i) cin >> ma[i];
opt = 0;
for (int i = 0;i<n;++i)
{
for (int j = 0;j<m;++j)
{
if (ma[i][j]>='0' && ma[i][j]<='9')
{
if (ma[i][j] == '1')
{
sx = i;
sy = j;
} else
{
opt |= (getDir(i,j,ma[i][j]-'1')<<((ma[i][j]-'2')*2));
// cout << i << " " << j << " " << (getDir(i,j,ma[i][j]-'1')) << endl;
}
len = max(len,ma[i][j]-'1');
}
if (ma[i][j] == '@') {tx = i; ty = j;}
}
}
mask = (1<<(len*2))-1;
que.push((NODE){sx,sy,opt});
dp[sx][sy][opt] = 1;
int tag;// excellent! 这让我们没必要每次清零in
while (!que.empty())
{
int x = que.front().x;
int y = que.front().y;
int opt = que.front().opt;
int dx = x,dy = y, dopt = opt;
in[dx][dy] = ++tag;
for (int i = 0;i<len-1;++i)
{
int dir = (dopt & 3);
dx += dirx[dir];
dy += diry[dir];
dopt >>= 2;
in[dx][dy] = tag;
}
que.pop();
for (int i = 0;i<4;++i)
{
dx = x + dirx[i];
dy = y + diry[i];
dopt = ( ((opt<<2) & mask) | (i^2) );
if (dx<0 || dx>=n || dy<0 || dy>=m
|| ma[dx][dy] == '#' || in[dx][dy] == tag
|| dp[dx][dy][dopt]>0) continue;
dp[dx][dy][dopt] = dp[x][y][opt]+1;
que.push((NODE){dx,dy,dopt});
}
}
int ans = inf;
for (int i = 0;i<1<<16;++i)
if (dp[tx][ty][i]>0)
{
ans = min(ans,dp[tx][ty][i]);
}
if (ans == inf) cout << "-1" << endl; else
cout << ans-1 << endl;
return 0;
}
E:
果断智商捉鸡啊…围观大神们代码,发现神奇的大家都弄了个表,脑小理解不能,直到出了题解… 梅森数什么的…不和谐啊.这种东西居然大家都知道?下面是官网的题解.
Author is Ripatti .
You havez = [x / 2] + y + xy. That is equivalent to
z = [2k / 2] + y + 2ky,where x = 2k, k > 0
or
z = [(2k + 1) / 2] + y + (2k + 1)y, where x = 2k + 1, k ≥ 0.
z = k + y + 2ky, k > 0
or
z = k + y + (2k + 1)y, k ≥ 0.
Stillmore steps:
2z + 1 = 2k + 2y + 4ky + 1, k > 0
or
z + 1 = k + 2y + 2ky + 1, k ≥ 0.
2z + 1 = (2k + 1)(2y + 1), k > 0
or
z + 1 = (2y + 1)(k + 1), k ≥ 0.
From the2nd equation you can see than z should be 2t - 1 because otherwise z + 1 willhave odd divisor and we can build solution. From the 1st equation you can seethat 2t + 1 - 1 should be prime, otherwise we also can build solution. If z = 2t - 1and 2t + 1 - 1 is prime, obliviously there are no solutions.
#include <iostream>
#include <cstdio>
using namespace std;
const int MOD = 1000000007;
int a[40] = {2,3,5,7,13,17,19,31,61,89,107,127,521,607,1279,2203,2281,3217,4253,4423,9689,9941,11213,19937,21701,23209,44497,
86243,110503,132049,216091,756839,859433,1257787,1398269,2976221,3021377,6972593,13466917,20996011};
int main() {
int n;
scanf("%d",&n);
int x = 1;
for (int i=1;i<a[n-1];i++) {
x *= 2;
if (x >= MOD) x -= MOD;
}
printf("%d\n",(x+MOD-1) % MOD);
return 0;
}