最后一次比赛了,虽然打铁了,但是并不可惜,三人都尽了全力,坚持到了比赛的最后一刻,每个人都在为了这个团队付出,这才是比赛的意义所在。
2017新疆乌鲁木齐icpc题目偏向数学,稳铜的4题都是数学题。
B和G是两个签到题,看手速。
D题正解是推出一个组合数的式子,我们用的是矩阵快速幂(全场过这题的估计没几个用这个的)。队友找的是三层的递推关系,我构造了6*6的矩阵,一切顺风顺水敲出了代码,但是前期一直TLE,最后半小时走投无路瞎改,竟然改对了???
把指数取模直接过了???不符合数学常理啊,应该是数据水(不这么解释有些颠覆世界观啊)。
K题一直没明白队友说的题意和他的思路,自己看了一会儿理解透题意后立马反应到最后结果是对一个n,小于n的并且与n互质的数的平方和。那么可能是有素数分解和容斥的,前些天刚做过两三道这样的题,立马有了思路。由于我准备的比较充分,1^2+2^2+3^2+……+n^2的公式直接记了,素数分解的过程也想清楚了,容斥的二进制枚举的过程也想清楚了(后来发了官方题解发现和我的思路一模一样),敲上去之后一直提示一个好像是浮点错误的消息,直接出不了结果(这实在是太打击人了,明明是把一个数素数分解,这个数整除任意个素因子累积,结果必然是一个整数,就算不是整数,两个long long 类型的碰到/运算符也是整除的意思,怎么会莫名其妙出现浮点数错误呢?),最后这题让队友调试他的直接暴力的代码了,一直T到最后,无果。
最终结果是过了三题,后来在飞机上想了想我的容斥的方法,确实是一点毛病也没有,而且符合ICPC的基本考点,还好打印了一个版本的代码,赛后调了不一会儿就出数了,代码如下,等待验证其正确性。
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
int MOD=998244353;
LL Stack[1000],top,Cnt[1000],tmp[1000];
void fenjie(LL k)
{
top=0;
memset(Cnt,0,sizeof(Cnt));
for(LL i=2;i*i<=k;i++)if(k%i==0)
{
while(k%i==0)Cnt[top]++,k/=i;
Stack[top++]=i;
}
if(k>1)
{
Cnt[top]++;
Stack[top++]=k;
}
}
LL quick(LL m,LL n)
{
LL b=1;
while(n>0)
{
if(n&1)b=(b*m)%MOD;
n=n>>1;
m=(m*m)%MOD;
}
return b;
}
LL f(LL n)
{
LL ans=(((n*(n+1))%MOD)*(((2*n)%MOD+1)%MOD))%MOD;//cout<<"a="<<ans;
ans=(ans*quick(6,MOD-2))%MOD;//cout<<" b="<<ans<<endl;
return ans;
}
LL solve(LL a)
{
LL ans1=0;
for(LL i=1;i<(1<<top);i++)
{
LL sum=0,ans=1;
for(LL j=0;j<top;j++)
if(i&(1<<j))
{
sum++;
ans=(ans*Stack[j])%MOD;
}
if(sum&1)
ans1=(ans1+((f(a/ans)*ans)%MOD*ans)%MOD)%MOD;
else
ans1=(ans1-((f(a/ans)*ans)%MOD*ans)%MOD+MOD)%MOD;
}
return ans1;
}
int main()
{
int t;
LL n;
scanf("%d",&t);
while(t--)
{
scanf("%lld",&n);
fenjie(n);
/*for(LL i=0;i<top;i++)
cout<<Stack[i]<<" ";
cout<<endl<<endl;
for(LL i=0;i<top;i++)
cout<<Cnt[i]<<" ";
cout<<endl;*/
LL anss=f(n);
LL ass=solve(n);//cout<<anss<<" "<<ass<<" ";
anss=((anss-ass)+MOD)%MOD;
printf("%lld\n",anss);
}
return 0;
}