A题:
水题不用说,乱搞搞就过了。
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
using namespace std;
int map[51][51];
int main()
{
int i,j,a,b,c,d,T,n,p;
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&p);
memset(map,0,sizeof(map));
for(i=1;i<=n;i++)
{
a=i;b=i+1;
c=i;d=i+2;
if(b>n)b=b-n;
if(d>n)d=d-n;
map[a][b]=map[b][a]=1;
map[c][d]=map[d][c]=1;
}
int ad=3;
while(1)
{
if(p==0)break;
for(i=1;i<=n;i++)
{
a=i;
b=i+ad;
if(b>n)b=b-n;
if(map[a][b]==0)
{
map[a][b]=map[b][a]=1;
p--;
if(p==0)break;
}
}
if(p==0)break;
ad++;
}
for(i=1;i<=n;i++)
{
for(j=i+1;j<=n;j++)
{
if(map[i][j])
{
cout<<i<<" "<<j<<endl;
}
}
}
}
return 0;
}
B题:
由题意可知:
f(x):x所有的因子,如果某个因子为坏素数,结果-1,如果为好素数,结果+1;
a数组中的数可以做无数次操作。
假如两次操作i,j。如果i先操作,j后操作。那么i操作的r一定大于j操作的r。
那么就可以从a数组的后面往前面搜。
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
#include<math.h>
using namespace std;
int as[110000],prime[110000];
int num,N;
void Prime()
{
memset(as, 0, sizeof(as));
int i, j;
num=0;
for(i = 2; i < N; ++i)
{
if(!(as[i])) prime[num++] = i;
for(j = 0; (j<num && i*prime[j]<N); ++j)
{
as[i*prime[j]] = 1;
if(!(i%prime[j])) break;
}
}
}
int gcd(int n,int m)
{
if(n<m)swap(n,m);
if(m==0)return n;
return gcd(m,n%m);
}
int a[10000];
int b[10000];
int g[10000];
int dp[2][10000];
int n,m;
int inb(int x)
{
int l=1;
int r=m+1;
int mid=(l+r)/2;
while(l<r)
{
if(b[mid]>x)r=mid;
if(b[mid]<x)l=mid+1;
if(b[mid]==x)return 1;
mid=(l+r)/2;
}
return 0;
}
int dos(int x)
{
int st,ans,ps,i;
st=ans=0;
int sqx;
for(i=0; i<num; i++)
{
sqx=sqrt(x);ps=prime[i];
if(ps>sqx)break;
st=0;
if(x%ps==0)
{
while(x%ps==0)
{
x=x/ps;
st++;
}
if(inb(ps))ans-=st;
else ans+=st;
}
}
if(x!=1)
{
ps=x;st=1;
if(inb(ps))ans-=st;
else ans+=st;
}
return ans;
}
int main()
{
int T,i,j;
N=100000;
Prime();
while(~scanf("%d%d",&n,&m))
{
memset(dp,0,sizeof(dp));
for(i=1; i<=n; i++)scanf("%d",&a[i]);
for(j=1; j<=m; j++)scanf("%d",&b[j]);
sort(b+1,b+m+1);
g[1]=a[1];
for(i=2; i<=n; i++)
{
g[i]=gcd(g[i-1],a[i]);
}
for(i=1;i<=n;i++)
{
dp[0][i]=dp[0][i-1]+dos(a[i]);
}
int maxx=0;
maxx=dp[0][n];
int t=1;
for(i=n;i>=1;i--)
{
int kk=g[i]/t;
int pp=dos(kk);
if(pp<0)
{
t=g[i];
maxx-=i*pp;
}
}
cout<<maxx<<endl;
}
return 0;
}
C题:
从代码上来讲,我感觉c题比b题好写多了。。。
C题给你一个矩阵。问你矩阵的任意次方之后,会不会出现矩阵上的所有的数字都大于0.
一个矩阵a[i][j]>0,代表ij之间可走。
那么本题就化身为给定一个图,问,任意两点之间是否可达。
那么本题就化身为给定一个图,然后tarjan算法求缩点,看最后是否会缩成一个点。
By rowanhao, contest: Codeforces Round #236 (Div. 1), problem: (C) Strictly Positive Matrix, Accepted, #
#include<stdio.h>
#include<algorithm>
#include<iostream>
#include<string.h>
#include<stack>
using namespace std;
#define maxn 3001
struct list
{
int u;
int v;
int next;
}edge[4400000];
int head[4400000];
int low[maxn];
int dnf[maxn];
int instack[maxn];
int times;
int num;
int nums;
int n;
void init()
{
memset(head,-1,sizeof(head));
num=0;
nums=0;
times=0;
memset(dnf,0,sizeof(dnf));
memset(instack,0,sizeof(instack));
memset(low,0,sizeof(low));
}
void add(int u,int v)
{
edge[num].u=u;
edge[num].v=v;
edge[num].next=head[u];
head[u]=num++;
}
stack<int>qq;
void tarjan(int x)
{
dnf[x]=low[x]=times++;
instack[x]=1;
qq.push(x);
for(int i=head[x];i!=-1;i=edge[i].next)
{
int y=edge[i].v;
if(!dnf[y])
{
tarjan(y);
low[x]=min(low[x],low[y]);
}
else if(instack[y])
{
low[x]=min(low[x],dnf[y]);
}
}
if(low[x]==dnf[x])
{
int y=-1;
while(x!=y)
{
y=qq.top();
qq.pop();
instack[y]=0;
}
nums++;
}
}
int main()
{
int i,j,x;
while(~scanf("%d",&n))
{
init();
for(i=1;i<=n;i++)
{
for(j=1;j<=n;j++)
{
scanf("%d",&x);
if(x)
{
add(i,j);
}
}
}
for(i=1;i<=n;i++)
{
if(!dnf[i])
{
tarjan(i);
}
}
if(nums>1)
{
cout<<"NO"<<endl;
}
else cout<<"YES"<<endl;
}
}
水题不用说,乱搞搞就过了。
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
using namespace std;
int map[51][51];
int main()
{
int i,j,a,b,c,d,T,n,p;
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&p);
memset(map,0,sizeof(map));
for(i=1;i<=n;i++)
{
a=i;b=i+1;
c=i;d=i+2;
if(b>n)b=b-n;
if(d>n)d=d-n;
map[a][b]=map[b][a]=1;
map[c][d]=map[d][c]=1;
}
int ad=3;
while(1)
{
if(p==0)break;
for(i=1;i<=n;i++)
{
a=i;
b=i+ad;
if(b>n)b=b-n;
if(map[a][b]==0)
{
map[a][b]=map[b][a]=1;
p--;
if(p==0)break;
}
}
if(p==0)break;
ad++;
}
for(i=1;i<=n;i++)
{
for(j=i+1;j<=n;j++)
{
if(map[i][j])
{
cout<<i<<" "<<j<<endl;
}
}
}
}
return 0;
}
B题:
由题意可知:
f(x):x所有的因子,如果某个因子为坏素数,结果-1,如果为好素数,结果+1;
a数组中的数可以做无数次操作。
假如两次操作i,j。如果i先操作,j后操作。那么i操作的r一定大于j操作的r。
那么就可以从a数组的后面往前面搜。
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
#include<math.h>
using namespace std;
int as[110000],prime[110000];
int num,N;
void Prime()
{
memset(as, 0, sizeof(as));
int i, j;
num=0;
for(i = 2; i < N; ++i)
{
if(!(as[i])) prime[num++] = i;
for(j = 0; (j<num && i*prime[j]<N); ++j)
{
as[i*prime[j]] = 1;
if(!(i%prime[j])) break;
}
}
}
int gcd(int n,int m)
{
if(n<m)swap(n,m);
if(m==0)return n;
return gcd(m,n%m);
}
int a[10000];
int b[10000];
int g[10000];
int dp[2][10000];
int n,m;
int inb(int x)
{
int l=1;
int r=m+1;
int mid=(l+r)/2;
while(l<r)
{
if(b[mid]>x)r=mid;
if(b[mid]<x)l=mid+1;
if(b[mid]==x)return 1;
mid=(l+r)/2;
}
return 0;
}
int dos(int x)
{
int st,ans,ps,i;
st=ans=0;
int sqx;
for(i=0; i<num; i++)
{
sqx=sqrt(x);ps=prime[i];
if(ps>sqx)break;
st=0;
if(x%ps==0)
{
while(x%ps==0)
{
x=x/ps;
st++;
}
if(inb(ps))ans-=st;
else ans+=st;
}
}
if(x!=1)
{
ps=x;st=1;
if(inb(ps))ans-=st;
else ans+=st;
}
return ans;
}
int main()
{
int T,i,j;
N=100000;
Prime();
while(~scanf("%d%d",&n,&m))
{
memset(dp,0,sizeof(dp));
for(i=1; i<=n; i++)scanf("%d",&a[i]);
for(j=1; j<=m; j++)scanf("%d",&b[j]);
sort(b+1,b+m+1);
g[1]=a[1];
for(i=2; i<=n; i++)
{
g[i]=gcd(g[i-1],a[i]);
}
for(i=1;i<=n;i++)
{
dp[0][i]=dp[0][i-1]+dos(a[i]);
}
int maxx=0;
maxx=dp[0][n];
int t=1;
for(i=n;i>=1;i--)
{
int kk=g[i]/t;
int pp=dos(kk);
if(pp<0)
{
t=g[i];
maxx-=i*pp;
}
}
cout<<maxx<<endl;
}
return 0;
}
C题:
从代码上来讲,我感觉c题比b题好写多了。。。
C题给你一个矩阵。问你矩阵的任意次方之后,会不会出现矩阵上的所有的数字都大于0.
一个矩阵a[i][j]>0,代表ij之间可走。
那么本题就化身为给定一个图,问,任意两点之间是否可达。
那么本题就化身为给定一个图,然后tarjan算法求缩点,看最后是否会缩成一个点。
By rowanhao, contest: Codeforces Round #236 (Div. 1), problem: (C) Strictly Positive Matrix, Accepted, #
#include<stdio.h>
#include<algorithm>
#include<iostream>
#include<string.h>
#include<stack>
using namespace std;
#define maxn 3001
struct list
{
int u;
int v;
int next;
}edge[4400000];
int head[4400000];
int low[maxn];
int dnf[maxn];
int instack[maxn];
int times;
int num;
int nums;
int n;
void init()
{
memset(head,-1,sizeof(head));
num=0;
nums=0;
times=0;
memset(dnf,0,sizeof(dnf));
memset(instack,0,sizeof(instack));
memset(low,0,sizeof(low));
}
void add(int u,int v)
{
edge[num].u=u;
edge[num].v=v;
edge[num].next=head[u];
head[u]=num++;
}
stack<int>qq;
void tarjan(int x)
{
dnf[x]=low[x]=times++;
instack[x]=1;
qq.push(x);
for(int i=head[x];i!=-1;i=edge[i].next)
{
int y=edge[i].v;
if(!dnf[y])
{
tarjan(y);
low[x]=min(low[x],low[y]);
}
else if(instack[y])
{
low[x]=min(low[x],dnf[y]);
}
}
if(low[x]==dnf[x])
{
int y=-1;
while(x!=y)
{
y=qq.top();
qq.pop();
instack[y]=0;
}
nums++;
}
}
int main()
{
int i,j,x;
while(~scanf("%d",&n))
{
init();
for(i=1;i<=n;i++)
{
for(j=1;j<=n;j++)
{
scanf("%d",&x);
if(x)
{
add(i,j);
}
}
}
for(i=1;i<=n;i++)
{
if(!dnf[i])
{
tarjan(i);
}
}
if(nums>1)
{
cout<<"NO"<<endl;
}
else cout<<"YES"<<endl;
}
}