牛客月赛12-华华给月月出题-(线性筛)

C

题意:
就是给你n,让你求出i从1到n,i的n次方的异或和。

思考:
如果直接对1到n每次求ksm,肯定会超时。其实这种题只要范围比较大,一般都是线性筛,要么是O(nlogn)这个数会出现多少次:many sum。要么就是O(n)的筛法:有毒的玻璃球。要么就是欧拉晒中间取维护一些东西。这题用到了一个性质就是任何一个数都可以表示为一个质数和另一个数的乘积,所以每次求ksm只会对质数求罢了,别的都是直接晒出来。

代码:

欧拉晒维护一些值:

int T,n,m,k;
ll res[N];
bool st[N];
int pri[N],cnt;

ll ksm(ll a,ll b)
{
	ll sum = 1;
	while(b)
	{
		if(b&1) sum = sum*a%mod;
		b >>= 1;
		a = a*a%mod;
	}
	return sum;
}

void init(int x)
{
	res[1] = 1;
	for(int i=2;i<=x;i++)
	{
		if(!st[i])
		{
			pri[++cnt] = i;
			res[i] = ksm(i,n)%mod;
		}
		for(int j=1;pri[j]*i<=x;j++)
		{
			st[pri[j]*i] = 1;
			res[pri[j]*i] = res[i]*res[pri[j]]%mod; //i*pri[j]可以直接被表示出来,这里res[i]和res[pri[j]]的值肯定已经晒出来过了
			if(i%pri[j]==0) break;
		}
	}
}

signed main()
{
	IOS;
	cin>>n;
	init(n);
	ll anw = 0;
	for(int i=1;i<=n;i++) anw ^= res[i];
	cout<<anw;
	return 0;
}

many sum代码:

int T,n,m,k;
int va[N];
int sum[N];

void init()
{
	for(int i=1;i<=n;i++)
	{
		for(int j=i;j<=n;j+=i)
		sum[j] += va[i];
	}	
}

signed main()
{
	IOS;
	cin>>n>>va[1]>>m;
	for(int i=2;i<=n;i++) va[i] = (va[i-1]+7*i)%m;
	init();
	int ans = 0;
	for(int i=1;i<=n;i++) ans ^= sum[i];
	cout<<ans;
	return 0;
}

有毒的玻璃球代码:

int T,n,m,k;
int va[N];
int sum[N];
 
int ksm(int a,int b)
{
    int sum = 1;
    while(b)
    {
        if(b&1) sum = sum*a%mod;
        a = a*a%mod;
        b >>= 1;
    }
    return sum;
}
 
signed main()
{
    IOS;
    cin>>n>>m;
    int ans = 0;
    for(int i=1;i<=n;i++)
    {
        int sum = n/i;
        ans = (ans+sum*ksm(i,m)%mod)%mod;
    }
    cout<<ans;
    return 0;
}

总结:
多多积累经验呀,就和以前做过的题或者学过的算法联合起来。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值