记录一下昨天做pku campus 2016的过程吧(赛后查了查,也没有题解,于是乎将自己写的题的想法留下来,希望对大家有些帮助)。
比赛链接:http://poj.openjudge.cn/campus2016/
A题:
签到题。
#include
#include
using namespace std;
long long T;
double ansm,ri;
int ansi,n,li,p;
double tmp;
int main()
{
cin>>T;
while(T--)
{
ansi=0;ansm=0;
tmp=-1;
cin>>n>>p;
for(int i=1;i<=n;i++)
{
cin>>li>>ri;
if(li>p)continue;
if(ri>tmp){tmp=ri;ansi=i;}
}
cout<
B题:
这是一个后期题。
这题需要很好的题感,我们队在探索了一番后大胆猜想,不会有超过3的解(不会证,camp上有人说这个是个比较难的问题,有专门的论文),那么就希望最好的情况是能一直构造出3的解,因为2的解是显然存在的。设首项的下标为b,第二项为b + d1,第三项为b + d2 + d1,则需寻找d1和d2使得原数列中这三项成等差数列。代入化简,再设d1 = d2 + x,发现x 取2b + 1的时候,可以构造出一个解,b,5b + 2,7b + 3。于是写一个大数就可以了。容我吐槽一下(一向稳定的队友这一题wa了好多发,让我开始怀疑我的猜想对不对了--)
#include
#include
#include
#include
using namespace std;
#define N 1010
int T;
int a[N],b[N],c[N],d[N],e[N];
char s[N];
int n;
int main(){
scanf("%d",&T);
while (T--){
scanf("%s",s);
printf("%d\n",3);
printf("%s\n",s);
n=strlen(s);
memset(a,0,sizeof(a));
for (int i=0;i'0';
memset(b,0,sizeof(b));
for (int i=1;i<=n;i++){
b[i]+=5*a[i];
b[i+1]+=b[i]/10;
b[i]%=10;
}
while (b[n+1]!=0) n++;
b[1]+=2;
for (int i=1;i<=n;i++){
if (b[i]>=10){
b[i]-=10;
b[i+1]++;
}
else break;
}
while (b[n+1]!=0) n++;
for (int i=n;i;i--) printf("%d",b[i]);
printf("\n");
memset(b,0,sizeof(b));
for (int i=1;i<=n;i++){
b[i]+=7*a[i];
b[i+1]+=b[i]/10;
b[i]%=10;
}
while (b[n+1]!=0) n++;
b[1]+=3;
for (int i=1;i<=n;i++){
if (b[i]>=10){
b[i]-=10;
b[i+1]++;
}
else break;
}
while (b[n+1]!=0) n++;
for (int i=n;i;i--) printf("%d",b[i]);
printf("\n");
}
}
//58698582
//29349306
//30
C题:
这题题意难懂,队友说类似于数位dp,写了会儿a了。我也没看题,就贴个代码仅供参考吧。
队友1的代码:
#include
#include
#include
#define MOD 20160508
#define NN 1010
#define MM 10010
using namespace std;
long long T;
int n;
int c,n1,n2;
int m,x0,x;
int f[1010][1010][2];
int g[1010][1010];
int to[MM],w[MM],nex[MM],ver[NN],tot;
void addedge(int u,int v,int stamp)
{
to[++tot]=v;
w[tot]=stamp;
nex[tot]=ver[u];
ver[u]=tot;
return ;
}
int r[1010],bs;
int l[1010];
int ansl[1010],ans[1010];
void bfs()
{
memset(f,0,sizeof(f));
memset(g,0,sizeof(g));
memset(ans,0,sizeof(ans));
f[0][0][1]=1;
g[0][0]=1;
for(int len=0;len<=bs;len++)
{
for(int i=0;i<=c;i++)
{
if(g[len][i])
{
for(int j=ver[i];j;j=nex[j])
{
g[len+1][to[j]]=(g[len+1][to[j]]+g[len][i])%MOD;
}
}
if(f[len][i][1])
{
for(int j=ver[i];j;j=nex[j])
{
if(w[j]==r[len+1])f[len+1][to[j]][1]=(f[len+1][to[j]][1]+f[len][i][1])%MOD;
if(w[j]1]) f[len+1][to[j]][0]=(f[len+1][to[j]][0]+f[len][i][1])%MOD;
}
}
if(f[len][i][0])
{
for(int j=ver[i];j;j=nex[j])
{
f[len+1][to[j]][0]=(f[len+1][to[j]][0]+f[len][i][0])%MOD;
}
}
if(len==bs)ans[i]=(ans[i]+f[len][i][0]+f[len][i][1])%MOD;
else ans[i]=(ans[i]+g[len][i])%MOD;
}
}
return ;
}
char st1[1010],st2[1010];
int main()
{
cin>>T;
while(T--)
{
cin>>st1>>st2;
cin>>c;
cin>>n1;
tot=0;
memset(ver,0,sizeof(ver));
for(int i=1;i<=n1;i++)
{
cin>>m>>x;
addedge(0,x,m);
}
cin>>n2;
for(int i=1;i<=n2;i++)
{
cin>>x0>>m>>x;
addedge(x0,x,m);
}
//cout<<"st1:"<
// cout<<"st2:"<
bs=strlen(st1);
for(int i=1;i<=bs;i++)l[i]=st1[bs-i]-'0';
l[1]--;
for(int i=1;i<=bs;i++)if(l[i]<0){l[i+1]--;l[i]+=10;}
while(l[bs]==0)bs--;
for(int i=1;i<=bs;i++)r[i]=l[bs+1-i];
//cout<<"r: ";
//for(int i=1;i<=bs;i++)cout<
bfs();
for(int i=1;i<=c;i++)ansl[i]=ans[i];
bs=strlen(st2);
for(int i=1;i<=bs;i++)r[i]=st2[i-1]-'0';
//cout<<"r: ";
// for(int i=1;i<=bs;i++)cout<
bfs();
//cout<<"~~~"<
for(int i=1;i<=c;i++)
{
//cout<
long long tmp=ans[i]-ansl[i];
tmp=(tmp%MOD+MOD)%MOD;
cout<<(ans[i]-ansl[i]+MOD)%MOD<//cout<<"!!!!"<
}
return 0;
}
队友2的代码:
#include
#include
#include
#include
using namespace std;
#define N 1005
#define M 20010
#define MOD 20160508
int head[N],ver[M],edge[M],nex[M],tot;
char s1[N],s2[N];
int a[N];
int C;
long long f1[N],f2[N],g[N][N][3];
void add(int x,int y,int z){
ver[++tot]=y;
edge[tot]=z;
nex[tot]=head[x];
head[x]=tot;
}
void bfs(char s[],long long f[]){
int n=strlen(s);
for (int i=1;i<=n;i++) a[i]=s[i-1]-'0';
memset(g,0,sizeof(g));
g[0][0][1]=1;
for (int len=1;len<=n;len++){
for (int x=0;x<=C;x++){
for (int i=head[x];i;i=nex[i]){
int y=ver[i];
g[len][y][0]=(g[len][y][0]+g[len-1][x][0]) % MOD;
if (edge[i]0]=(g[len][y][0]+g[len-1][x][1]) % MOD;
g[len][y][2]=(g[len][y][2]+g[len-1][x][2]) % MOD;
}
else if (edge[i]==a[len]){
g[len][y][1]=(g[len][y][1]+g[len-1][x][1]) % MOD;
g[len][y][2]=(g[len][y][2]+g[len-1][x][2]) % MOD;
}
else if (edge[i]>a[len]){
g[len][y][2]=(g[len][y][2]+g[len-1][x][1]+g[len-1][x][2]) % MOD;
}
// cout<
}
}
}
for (int i=1;i<=C;i++){
for (int len=1;len// cout<
f[i]=(f[i]+g[len][i][0]+g[len][i][1]+g[len][i][2]) % MOD;
}
f[i]=(f[i]+g[n][i][0]+g[n][i][1]) % MOD;
// cout<
}
return ;
}
int main(){
int T;
scanf("%d",&T);
while (T--){
scanf("%s",s1);
for (int i=strlen(s1)-1;i>=0;i--){
if (s1[i]>='1'){
s1[i]--;
break;
}
else s1[i]='9';
}
scanf("%s",s2);
int N1,N2;
scanf("%d",&C);
scanf("%d",&N1);
tot=0;
memset(head,0,sizeof(head));
for (int i=1;i<=N1;i++){
int m,x;
scanf("%d%d",&m,&x);
add(0,x,m);
}
scanf("%d",&N2);
for (int i=1;i<=N2;i++){
int x0,m,x;
scanf("%d%d%d",&x0,&m,&x);
add(x0,x,m);
}
memset(f1,0,sizeof(f1));
memset(f2,0,sizeof(f2));
bfs(s1,f1);
bfs(s2,f2);
for (int i=1;i<=C;i++){
long long ans=(f2[i]-f1[i]+MOD)%MOD;
printf("%lld\n",ans);
}
}
return 0;
}
接下来几个比较简单的代码都是我写的。--
D题:
经典构造,一开始给了个构造,发现超范围了。
后来fix了一下。
3∗2n−1,2n,2n−2,2n−3,......,4,3,1
注意范围,小的时候可能构造点其他的。
#include
#include
#include
#include
using namespace std;
struct bignum{
int len;
int a[105];
bignum(int x){
len = 0;
memset(a,0,sizeof(a));
while(x > 0){
a[len++] = x % 10;
x /= 10;
}
}
void mul2(){
for(int i = 0;i < len;i++){
a[i] = a[i] * 2;
}
for(int i = 0;i < len;i++){
a[i + 1] += a[i] / 10;
a[i] = a[i] % 10;
}
if(a[len] > 0) len++;
}
void mul4(){
for(int i = 0;i < len;i++){
a[i] = a[i] * 4;
}
for(int i = 0;i < len;i++){
a[i + 1] += a[i] / 10;
a[i] = a[i] % 10;
}
if(a[len] > 0) len++;
}
void print(){
for(int i = len - 1;i >= 0;i--){
printf("%d",a[i]);
}
puts("");
}
};
int main(){
int T;
cin >> T;
while(T--){
int n;
cin >> n;
//bignum a = bignum(1);
//bignum b = bignum(3);
if(n == 1){
printf("1\n");
}else if(n == 2){
printf("-1\n");
}else if(n == 3){
printf("1\n2\n3\n");
}else if(n == 4){
printf("16\n24\n6\n2\n");
}else if(n > 4){
int N = n - 1;
bignum a(1);
for(int i = 0;i <= N;i++){
if(i != N - 1 && i != 1){
a.print();
}
a.mul2();
}
bignum b(3);
b.print();
for(int i = 1;i < N;i++) b.mul2();
b.print();
}
}
return 0;
}
E、F这种很难的题弱渣表示不会。
G题:
照着构图,跑spfa就可以了。
#include
#include
#include
#include
#include
#include
using namespace std;
const int maxn = 1000000 + 5;
const int INF = 0x3f3f3f3f;
vectorint ,int> > G[maxn];
void addEdge(int u,int v,int w){
G[u].push_back(make_pair(v,w));
}
void buildGraph(int N, int Seed) {
int nextRand = Seed;
// initialize random number generator
for (int x = 1; x <= N; x++) {
// generate edges from Node x
int w = x % 10 + 1; // the weight of edges
int d = 10 - w; // the number of edges
for (int i = 1; i <= d; i++) {
addEdge(x, nextRand % N + 1, w);
// add a new edge into G
nextRand = nextRand * 233 % N;
}
addEdge(x, x % N + 1, w);
}
}
int dis[maxn];
bool inq[maxn];
void spfa(){
memset(dis,INF,sizeof(dis));
memset(inq,false,sizeof(inq));
queue<int >q;
q.push(1);
inq[1] = true;
dis[1] = 0;
while(!q.empty()){
int u = q.front();q.pop();
inq[u] = false;
for(int i = 0;i < G[u].size();i++){
int v = G[u][i].first;
int cost = G[u][i].second;
if(cost + dis[u] < dis[v]){
dis[v] = dis[u] + cost;
if(inq[v] == false){
q.push(v);
inq[v] = true;
}
}
}
}
}
int main(){
int T;
cin >> T;
while(T--){
int n,seed;
cin >> n >> seed;
for(int i = 1;i <= n;i++) G[i].clear();
buildGraph(n,seed);
spfa();
cout << dis[n] << endl;
}
return 0;
}
H题:
矩阵快速幂。
推推公式就可以看出来了。
具体见代码。
#include
#include
#include
#include
#include
using namespace std;
typedef long long ll;
const ll mod = 1e9 + 7;
typedef vector vec;
typedef vector mat;
mat mul(mat & A,mat & B){
mat C(A.size(),vec(B[0].size()));
for(int i = 0;i < A.size();i++){
for(int k = 0;k < A[0].size();k++)if(A[i][k] != 0){
for(int j = 0;j < B[0].size();j++){
C[i][j] = (C[i][j] + A[i][k] * B[k][j]) % mod;
}
}
}
return C;
}
mat qpow(mat A, ll n){
mat C(A.size(),vec(A.size()));
for(int i = 0;i < A.size();i++){
C[i][i] = 1;
}
while(n > 0){
if(n & 1) C = mul(C,A);
A = mul(A,A);
n >>= 1;
}
return C;
}
const int maxn = 20000 + 5;
long long n;
int m;
long long xo,yo;
int u[maxn],d[maxn],l[maxn],r[maxn];
int sum[maxn];
int add[maxn];
mat matrix[maxn];
int main(){
int T;
cin >> T;
while(T--){
cin >> n >> m >> xo >> yo;
for(int i = 1;i <= m;i++){
scanf("%d%d%d%d",u + i,d + i,l + i,r + i);
sum[i] = u[i] + d[i] + l[i] + r[i];
add[i] = u[i] + r[i] - l[i] - d[i];
mat A(2,vec(2));
A[0][0] = sum[i] + 1;
A[0][1] = add[i];
A[1][0] = 0;
A[1][1] = sum[i] + 1;
matrix[i] = A;
}
for(int i = 2;i <= m;i++){
matrix[i] = mul(matrix[i], matrix[i - 1]);
}
long long x = n / m;
long long y = n % m;
mat C = qpow(matrix[m],x);
if(y > 0)C = mul(C,matrix[y]);
long long ans = (xo + yo) % mod * C[0][0] + C[0][1];
cout << (ans % mod + mod) % mod << endl;
}
return 0;
}
I题:赛中只会数P
赛后去camp上提问了一下。
感觉大家的方法都很厉害。
其中还有关于B题的讨论。
https://async.icpc-camp.org/d/629-pku-campus-2016
J:
签到题喽。
#include
#include
#include
#include
using namespace std;
char s[11];
const int maxn = 1005;
int d[maxn];
int main(){
int n;
int T;
cin >> T;
while(T--){
cin >> n;
for(int i = 1;i <= n;i++){
scanf("%s",s);
if(s[0] == '#') d[i] = -1;
else{
int a = 0;
int len = strlen(s);
for(int i = 0;i < len;i++){
a = a * 10 + s[i] - '0';
}
d[i] = a;
}
}
if(n % 2 == 0){
printf("No\n");
}else{
bool flag = true;
for(int i = 1;i <= n;i++){
if(i & 1){
if(d[i] != -1) flag = false;
}else{
if(d[i] == -1) flag = false;
}
}
if(flag) printf("Yes\n");
else printf("No\n");
}
}
return 0;
}
总之这一场比赛感觉还不错。