链接
题意:给定斐波那契形式的字符串递推公式,然后让你输出第 n 个字符串从第 k 个字符开始的 10个字符。
思路:
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const ll maxn=500+10,MAX=1e12+10;
ll dp[maxn];
string s1="COFFEE";
string s2="CHICKEN";
char dfs(int n,ll k)
{
if(n==1) return s1[k-1];
if(n==2) return s2[k-1];
if(k<=dp[n-2]) return dfs(n-2,k);
else return dfs(n-1,k-dp[n-2]);
}
int main()
{
dp[1]=6,dp[2]=7;
for(int i=3;i<=500;++i)
{
dp[i]=dp[i-2]+dp[i-1];
dp[i]=min(dp[i],MAX);
}
ll t,n,k;
cin>>t;
while(t--)
{
cin>>n>>k;
for(ll i=k;i<=k+9&&i<=dp[n];++i)
cout<<dfs(n,i);
puts("");
}
return 0;
}
题意:给定曲线递归后的定义,然后让你给第 n 层曲线上的一些点,让你按访问的先后顺序输出这些点。
思路:
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const ll maxn=1e6+10,MAX=1e12;
int n,k;
ll d[maxn];
struct Point
{
int x,y,id;
bool operator<(const Point & b) const
{
return id<b.id;
}
}p[maxn];
ll dfs(int x,int y,int k)
{
if(k==0) return 1;
ll mid=1<<k-1;
ll s=mid*mid;
if(x<=mid&&y<=mid)
return dfs(y,x,k-1);
else if(x>mid&&y<=mid)
return s+dfs(x-mid,y,k-1);
else if(x>mid&&y>mid)
return 2*s+dfs(x-mid,y-mid,k-1);
else if(x<=mid&&y>mid)
return 3*s+dfs(mid-(y-mid)+1,mid-x+1,k-1);
}
int main()
{
cin>>n>>k;
for(int i=1;i<=n;++i)
{
cin>>p[i].x>>p[i].y;
p[i].id=dfs(p[i].x,p[i].y,k);
}
sort(p+1,p+1+n);
for(int i=1;i<=n;++i)
cout<<p[i].x<<" "<<p[i].y<<"\n";
return 0;
}
题意:给定 2n个人,每两个人之间有一个竞争值,将这 2n个人分配在两个队伍里,使得竞争值最大。只计算不同队伍,每两个人之间的竞争值。
思路:
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const ll maxn=1e6+10,MAX=1e12;
int n;
int v[30][30];
ll ans;
void dfs(int p,int mask,int k,ll cost)
{
if(k==n)
{
ans=max(ans,cost);
return;
}
for(int i=p;i<=2*n;++i)
{
ll tmp=cost;
for(int j=1;j<=2*n;++j)
{
if(mask>>j-1&1)
tmp-=v[i][j];
else tmp+=v[i][j];
}
dfs(i+1,mask+(1<<i-1),k+1,tmp);
}
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=2*n;++i)
for(int j=1;j<=2*n;++j)
scanf("%d",&v[i][j]);
ll cost=0;
for(int j=1;j<=2*n;++j)
cost+=v[1][j];
dfs(2,1,1,cost);
printf("%lld\n",ans);
return 0;
}
思路:
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const ll maxn=1e6+10,mod=1e9+7;
int qpow(int b,int n,int mod)
{
int res=1;
while(n)
{
if(n&1) res=1ll*res*b%mod;
b=1ll*b*b%mod;
n>>=1;
}
return res;
}
const int N=3000;
int fac[N+10],finv[N+10];
void init()
{
fac[0]=fac[1]=1;
for(int i=2;i<=N;++i)
fac[i]=1ll*fac[i-1]*i%mod;
finv[N]=qpow(fac[N],mod-2,mod);
for(int i=N-1;i>=0;--i)
finv[i]=1ll*finv[i+1]*(i+1)%mod;
}
int C(int n,int m)
{
return 1ll*fac[n]*finv[m]%mod*finv[n-m]%mod;
}
int t,n;
int dfs(int lim,int p,int pro,int sum,int cnt,int now)
{
if(p==n+1)
{
if(pro==sum)
return 1ll*finv[cnt]*now%mod*fac[n]%mod;
return 0;
}
if(pro==sum+n-p+1)
return 1ll*now*finv[cnt]%mod*finv[n-p+1]%mod*fac[n]%mod;
if(pro>sum+n-p+1) return 0;
if(pro*lim>sum+lim+n-p) return 0;
if(lim>n) return 0;
int ans=0;
ans=(ans+dfs(lim,p+1,pro*lim,sum+lim,cnt+1,now))%mod;
ans=(ans+dfs(lim+1,p,pro,sum,0,1ll*now*finv[cnt]%mod))%mod;
return ans;
}
int main()
{
init();
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
int ans=dfs(2,1,1,0,0,1);
printf("%d\n",ans);
}
return 0;
}
链接
题意:有 4 个队伍进行 6场比赛,赢的加3分,输的不加分。如果是平局双方各加一分。现在给定 4 个队伍最终的分数,问能不能根据分数还原出原来的比赛胜负情况。只有一种情况输出yes,多种情况输出no,分数不合理输出Wrong Scoreboard.
思路:
#include <bits/stdc++.h>
#define ll long long
using namespace std;
int t,a,b,c,d;
int x[10],visit[200000];
int calc(int a,int b,int c,int d)
{
return a*1000+b*100+c*10+d;
}
void f(int x,int &a,int &b)
{
if(x==0) a+=3;
else if(x==1) b+=3;
else if(x==2) a++,b++;
}
void dfs(int k)
{
if(k==7)
{
int a=0,b=0,c=0,d=0;
f(x[1],a,b);
f(x[2],a,c);
f(x[3],a,d);
f(x[4],b,c);
f(x[5],b,d);
f(x[6],c,d);
int res=calc(a,b,c,d);
visit[res]++;
return;
}
for(int i=0;i<=2;++i)
{
x[k]=i;
dfs(k+1);
}
}
int main()
{
dfs(1);
scanf("%d",&t);
int Case=0;
while(t--)
{
scanf("%d%d%d%d", &a,&b,&c,&d);
int x=calc(a,b,c,d);
printf("Case #%d: ",++Case);
if(visit[x]==0||(a>10||b>10||c>10||d>10)) puts("Wrong Scoreboard");
else if(visit[x]==1) puts("Yes");
else if(visit[x]>=2) puts("No");
}
return 0;
}
链接
题意:给定 n 根小木棍,用它们组成相同长度的大木棍,问最短的相同长度是多少
思路: n 最多为50,规模较小
#include <cstdio>
#include <cstring>
#include <algorithm>
#define ll long long
using namespace std;
const int maxn=100+10;
int n;
int a[maxn],visit[maxn];
bool dfs(int p,int now,int len,int k)
{
if(k==0&&now==0)
return 1;
if(k<0) return 0;
for(int i=p;i<=n;++i)
{
if(visit[i]) continue;
if(now+a[i]==len)
{
visit[i]=1;
if(dfs(1,0,len,k-1))
return 1;
else
{
visit[i]=0;
return 0;
}
}
if(now+a[i]<len)
{
visit[i]=1;
if(dfs(p+1,now+a[i],len,k-1))
return 1;
visit[i]=0;
}
if(now==0)
return 0;
}
return 0;
}
bool cmp(int a,int b)
{
return a>b;
}
int main()
{
while(scanf("%d",&n)&&n)
{
ll sum=0;
for(int i=1;i<=n;++i)
scanf("%d",&a[i]),sum+=a[i];
sort(a+1,a+1+n,cmp);
for(int i=a[1];i<=sum;++i)
{
if(sum%i!=0) continue;
memset(visit,0,sizeof(visit));
if(dfs(1,0,i,n))
{
printf("%d\n",i);
break;
}
}
}
return 0;
}
题意:给定 n 根木棍,问凑成一个正方形。
思路:和上题一样,需要记录位置 p,不然会超时。
#include <cstdio>
#include <cstring>
#include <algorithm>
#define ll long long
using namespace std;
const int maxn=100+10;
int n;
int a[maxn],visit[maxn];
bool dfs(int p,int now,int len,int k)
{
if(k==0&&now==0)
return 1;
if(k<0) return 0;
for(int i=p;i<=n;++i)
{
if(visit[i]) continue;
if(now+a[i]==len)
{
visit[i]=1;
if(dfs(1,0,len,k-1))
return 1;
else
{
visit[i]=0;
return 0;
}
}
if(now+a[i]<len)
{
visit[i]=1;
if(dfs(i+1,now+a[i],len,k-1))
return 1;
visit[i]=0;
}
if(now==0)
return 0;
}
return 0;
}
bool cmp(int a,int b)
{
return a>b;
}
int t;
int main()
{
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
ll sum=0;
for(int i=1;i<=n;++i)
scanf("%d",&a[i]),sum+=a[i];
sort(a+1,a+1+n,cmp);
for(int i=1;i<=n;++i) visit[i]=0;
if(sum%4||a[1]>sum/4)
{
puts("no");
continue;
}
if(dfs(1,0,sum/4,n))
puts("yes");
else puts("no");
}
return 0;
}
链接
题意:给定 p、q、a、n,最多用n个单位分数相加组成 p q \frac pq qp,单位分数的乘积不能超过a,求不同的方案数。 ( n ≤ 7 ) (n\le 7) (n≤7)
思路: 数据规模比较小
#include <cstdio>
#include <cstring>
#include <algorithm>
#define ll long long
using namespace std;
int ans;
void dfs(int x,int p,int q,int pro,int k,int a)
{
if(p==0&&k>=0)
{
ans++;
return;
}
if(p<0||k<0||k*q<p*x)
return;
for(int i=x;pro*i<=a;i++)
dfs(i,p*i-q,q*i,pro*i,k-1,a);
}
int p,q,a,n;
int main()
{
while(scanf("%d%d%d%d",&p,&q,&a,&n)&&(p||q||a||n))
{
ans=0;
dfs(1,p,q,1,n,a);
printf("%d\n",ans);
}
return 0;
}
题意:当前解决的问题为 0,花费了 0 分钟。每次都会选择花费时间大于等于上次解决问题的时间,问最多能够解决多少个问题
思路:
#include <cstdio>
#include <cstring>
#include <algorithm>
#define ll long long
using namespace std;
const int maxn=100+10;
int n;
int t[20][20],ans;
int visit[20];
void dfs(int p,int dif,int tot)
{
ans=max(ans,tot);
for(int j=1;j<=n;++j)
{
if(!visit[j]&&t[p][j]>=dif)
{
visit[j]=1;
dfs(j,t[p][j],tot+1);
visit[j]=0;
}
}
}
int main()
{
while(~scanf("%d",&n))
{
for(int i=1;i<=n;++i)
for(int j=1;j<=n;++j)
scanf("%d",&t[i][j]);
ans=1;
memset(visit,0,sizeof(visit));
visit[1]=1;
dfs(1,0,1);
printf("%d\n",ans);
}
return 0;
}
链接
思路:直接打表
打表程序
#include <cstdio>
#include <cstring>
#include <algorithm>
#define ll long long
using namespace std;
const int maxn=100+10;
int n;
int a[30][30],b[30];
int cnt[2],ans;
void dfs(int k)
{
if(k==n+1)
{
cnt[0]=cnt[1]=0;
for(int i=1;i<=n;++i) a[1][i]=b[i];
for(int i=2;i<=n;++i)
for(int j=1;j<=n-i+1;++j)
a[i][j]=a[i-1][j]^a[i-1][j+1];
for(int i=1;i<=n;++i)
for(int j=1;j<=n-i+1;++j)
cnt[a[i][j]]++;
if(cnt[0]==cnt[1])
ans++;
return;
}
b[k]=1;
dfs(k+1);
b[k]=0;
dfs(k+1);
}
int main()
{
for(n=1;n<=24;++n)
{
if(n*(n+1)%4)
{
printf("0,");
}
else
{
ans=0;
dfs(1);
printf("%d,",ans);
}
}
return 0;
}