题意:位数为偶数且为回文的正整数成为zcy数字,求前k个zcy数字的和对p取余
思路:先打印出前一百位找规律
我的规律:发现下一个zcy数是上一个zcy数从最中间的两个数往两边变化,如果不为‘9’那么就让这个数字加‘1’对称的那个数字也加一然后跳出,为‘9’就变为‘0’继续找,如果都最外层还是九那就需要在子串的两端各加一个‘1’。(感觉我这个想法有点蠢)
后来听了一个朋友的想法:第i个zcy数就是i和反序i的连接在一起,例如:第1个zcy数字位11,第2个为22,第10个zcy数就是1001,第123个zcy数位123321等等
所以我们模拟得到前N个zcy数字串转化为数字加起来然后对p取余就OK了。注意要用long long
#include<bits/stdc++.h>
using namespace std;
const int MAXN = 1e5 + 5;
int k,p;
long long a[MAXN];
long long get(int num)//得到 “num+反num”的数字
{
//数字转字符串
string s = "";
stringstream ss;
ss << num;
ss >> s;
string rs = s;
reverse(rs.begin(),rs.end());//字符串反转
s = s + rs;//连接正反字符串
//字符串转数字
long long a;
ss.clear();
ss << s;
ss >> a;
return a;
}
void init()
{
a[0] = 0;
for(int i = 1; i < MAXN; i++) //得到前MAXN个数字并做前缀和
{
a[i] = get(i);
a[i] += a[i - 1];
}
}
int main()
{
init();
while(~scanf("%d%d",&k,&p))
{
printf("%d\n",a[k] % p);
}
return 0;
}
#include<bits/stdc++.h>
using namespace std;
const int MAXN = 1e5 + 5;
long long a[MAXN];
string GZ(string s)//构造字符串
{
int len = s.length();
int i = len/2 - 1,j = len / 2;//两个指针同时往前后两边扫,互相对称
while(1)
{
if(i >= 0)
{
if(s[i] != '9')//不为9
{
s[i] = s[i] + 1;
s[j] = s[j] + 1;
break;
}
else
{
s[i] = '0';
s[j] = '0';
}
}
else
{
s.insert(s.begin(),'1');
s.insert(s.end(),'1');
break;
}
i--;j++;
}
return s;
}
void init()
{
string s = "11";
for(int i = 1; i < MAXN; i++)//构造字符串
{
s = GZ(s);
//字符串变数字
stringstream ss;
ss << s;
ss >> a[i];
}
a[0] = 11;
for(int i = 1; i < MAXN; i++) a[i] = a[i] + a[i - 1];//前缀和
}
int main()
{
init();
int k, p;
while(~scanf("%d%d",&k,&p))
{
printf("%d\n",a[k - 1] % p);
}
return 0;
}
/*
2 100
5 30
*/
本文介绍了一种求解特定回文数(ZCY数字)序列的算法,并提供了两种实现思路:一种通过逐个生成回文数并累加求和;另一种通过直接构造回文数并进行前缀和计算。

472

被折叠的 条评论
为什么被折叠?



