版权声明:原创,未经作者允许禁止转载 https://blog.csdn.net/Mr_wuyongcong/article/details/82955692
正题
T1:序言页码
评测记录:https://www.luogu.org/recordnew/lists?uid=52918&pid=P1465
题目大意
求 的罗马数字每个字母出现的次数。
解题思路
先写一个表,表示这个位上出现哪个数字表示
的字母出现次数和表示
的字母出现的次数。
然后直接计算
code
#include<cstdio>
#include<string>
using namespace std;
const char f[8]={' ','I','V','X','L','C','D','M'};
const int I[11]={0,1,2,3,1,0,1,2,3,1};
const int V[11]={0,0,0,0,1,1,1,1,1,0};
int n,c[8];
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
c[1]+=I[i%10];
c[2]+=V[i%10];
c[3]+=I[i%100/10]+(i%10==9);
c[4]+=V[i%100/10];
c[5]+=I[i%1000/100]+(i%100/10==9);
c[6]+=V[i%1000/100];
c[7]+=I[i/1000]+(i%1000/100==9);
}
for(int i=1;i<=7;i++)
if(c[i]) printf("%c %d\n",f[i],c[i]);
}
T2:集合
评测记录:https://www.luogu.org/recordnew/lists?uid=52918&pid=P1466
题目大意
求将 分解为两组且两组之和相等的方案数。
解题思路
用
表示前i个数,两组相差为j时的方案总数。
然后
然后得出的答案要除2,因为两组是一样的。
code
#include<cstdio>
#include<algorithm>
#define ll long long
using namespace std;
ll n,sum,f[40][801];
int main()
{
scanf("%lld",&n);
sum=0;
f[0][0]=1;
for(ll i=1;i<=n;i++)
{
sum+=i;
for(ll j=0;j<=sum;j++)
{
f[i][j]=f[i-1][abs(j-i)]+f[i-1][j+i];
}
}
printf("%lld",f[n][0]/2);
}
T3:循环数
评测记录:https://www.luogu.org/recordnew/lists?uid=52918&pid=P1467
题目大意
求比n大的第一个循环数(循环数就是每到达一个数字就往前走这个数字的步数,然后每个数字都走过一次)
解题思路
直接暴力往后加,然后看一下是不是循环数。
code
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
int n,now,k[10],a[10];
bool check(int x)
{
memset(k,0,sizeof(k));
int tmp=x,w=0;
while(tmp)
{
w++;
a[w]=tmp%10;
if(k[a[w]]) return false;
k[a[w]]=true;
tmp/=10;
}
for(int i=1;i<=w/2;i++)
swap(a[i],a[w-i+1]);
memset(k,0,sizeof(k));
tmp=1;
for(int i=1;i<=w;i++)
{
if(k[a[tmp]]||!a[tmp]) return false;
k[a[tmp]]=true;
tmp=(tmp+a[tmp]-1)%w+1;
}
if(tmp!=1) return false;
return true;
}//判断循环数
int main()
{
scanf("%d",&n);
now=n;
while(true)
{
now++;
if(check(now))
{
printf("%d",now);
break;
}
}
}
T4:派对灯
评测记录:https://www.luogu.org/recordnew/lists?uid=52918&pid=P1468
题目大意
有n个灯
有4种操作:
1.灯开着就关,关了就开
2.奇数号的取反
3.偶数号的取反
4.3k+1的灯取反
给出操作次数和某些灯的最终状态,求所有可能的状态
扫描二维码关注公众号,回复:
3488590 查看本文章
解题思路
我们可以发现其实灯就是6个一个的循环节。
然后一个东西操作过2次就没有用,然后1和2,3就等于按另一个
我们可以预处理除c=2可以做到的所有情况,然后c>2时也可以做到c=2时的效果
code
#include<cstdio>
using namespace std;
const int s[8]={0,14,21,27,36,42,49,63};//预处理可以做到的情况
int n,c,open,close,a[6],x;
bool flag;
void check(int x)
{
if((s[x]&open)!=open||s[x]&close) return;
int tmp=s[x],i=1;
while(tmp) a[6-i]=tmp%2,tmp/=2,i++;
for(int i=0;i<n;i++)
printf("%d",a[i%6]);
flag=true;
printf("\n");
}//判断这种情况是否满足
int main()
{
scanf("%d%d",&n,&c);
while(scanf("%d",&x)&&x!=-1)
x=6-(x-1)%6-1,open|=1<<x;//开启的等
while(scanf("%d",&x)&&x!=-1)
x=6-(x-1)%6-1,close|=1<<x;//关闭的灯
if(c==0) check(7);
if(c==1) check(0),check(2),check(3),check(5);
//前两个特判
if(c>=2)
for(int i=0;i<=7;i++) check(i);
if(!flag) printf("IMPOSSIBLE");
}