题意:
给一个数n(2<=n<=1e9),从1到n中选两个数字相加,得到n*(n-1)/2个结果,假设这些结果中末尾包含连续的9最多是x个,问这些结果中末尾包含连续x个9的数有多少个,即有多少种组合(x,y),(其中1<=x<=n,1<=y<=n,x!=y),x+y末尾包含连续x个9,其中(x,y)和(y,x)被视为同一种组合。
题解:
令sum代表n+n-1,如果sum是99999...99这种形式的话,则答案是1。
如果不是,假设sum有len位,则x是len-1,x是上面提到的x。则此时枚举最高为从0到8,分别得到09999..9,19999..9,29999...9。。。。。89999...9。令这些数是p。
如果p<=n+1,则有(p-1)/2种方案,这个很显然。。。
如果p>n+1&&p<=n+n-1,则有(2*n-p+1)/2种方案。这里说明一下,因为最大数是n,如果要组合成p的话,且p是大于n+1的,所以要求最小的数是p-n。则从p-n到n一共有n-(p-n)+1个数。再除以2就是方案数。
否则如果p>n+n-1,对答案无贡献。
对于n<=10的情况下,可以直接暴力。此时x最多是1。需要注意的是,如果任意的(x,y)的和末尾都没有9,则x是0,则所有组合都满足情况,答案是n*(n-1)/2。
某个步骤会爆int,所以用long long。
#include<bits/stdc++.h>
using namespace std;
const int MAXN=100;
const int INF=0x3f3f3f3f;
typedef long long ll;
int main()
{
// freopen("input.txt","r",stdin);
// freopen("output.txt","w",stdout);
int len=0;
ll n,x,sum,t=1ll;
cin>>n;
sum=n+n-1;
x=sum;
while(x)
{
len++;
x/=10;
t*=10;
}
if(sum==t-1) cout<<"1\n";
else if(n<=10)
{
int ans=0;
for(int i=1;i<=n;i++)
{
for(int j=i+1;j<=n;j++)
{
if((i+j)%10==9) ans++;
}
}
if(ans!=0) cout<<ans<<endl;
else cout<<n*(n-1)/2<<endl;
}
else
{
ll ans=0;
t/=10;
ll temp=t-1;
for(int i=0;i<=8;i++)
{
ll nt=t*i;
ll p=nt+temp;
if(p<=n+1) ans+=(p-1)/2;
else if(p>n+n-1) ;
else ans+=(2*n-p+1)/2;
}
cout<<ans<<endl;
}
return 0;
}