HDU 4407
这题不难吧,如果正在做组合的题。。。
使用容斥原理求解出(1~x)的与p互素的和,这是很容易的,很明显,首先要把p分解质因数。
而对于第二个操作,记录下他的转换的顺序,当要执行第一个操作时,遍历一次记录下的操作转换就可以了。
呃,这题虽然想到,但是,我的WA。看了网上的,思路和我的一样,我自己COPY别人的代码下来对拍数据,无误。。但就是过不了。能想到的边界数据也试过了,还是过不了。。求各路大神指错。
我的代码:
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#define Np 700
#define LL __int64
using namespace std;
bool isprime[Np];
LL prime[Np],np;
LL dsorp[Np],dp;
struct Update{
LL pos,val;
};
Update up[1500];
LL upp;
void initial(){
memset(isprime,true,sizeof(isprime));
np=0;
isprime[1]=false;
for(LL i=2;i<Np;i++){
if(isprime[i]){
prime[np++]=i;
for(LL j=i*i;j<Np;j+=i){
isprime[j]=false;
}
}
}
}
void dfs(LL i,LL num,LL tmp,LL &s,LL n){
if(i>=dp){
if(num==0){
s=(1+n)*n/2;
}
else{
LL sc=n/tmp;
if(num&1){
s=s-((sc+1)*sc/2*tmp);
}
else{
s=s+((sc+1)*sc/2*tmp);
}
}
return;
}
dfs(i+1,num,tmp,s,n);
dfs(i+1,num+1,tmp*dsorp[i],s,n);
}
LL work(LL x,LL y,LL p){
dp=0;
for(LL i=0;i<np&&prime[i]*prime[i]<=p;i++){
if(p%prime[i]==0){
dsorp[dp++]=prime[i];
while(p%prime[i]==0)
p=p/prime[i];
}
}
if(p>1)
dsorp[dp++]=p;
LL ansy,ansx;
ansy=ansx=0;
dfs(0,0,1,ansy,y);
dfs(0,0,1,ansx,x-1);
return ansy-ansx;
}
LL gcd(LL a,LL b){
if(b==0) return a;
return gcd(b,a%b);
}
bool coprime(LL a,LL p){
if(gcd(a,p)==1LL)
return true;
else return false;
}
int main(){
LL T,n,m,op,x,y,p,c;
initial();
scanf("%I64d",&T);
while(T--){
scanf("%I64d%I64d",&n,&m);
upp=0;
for(LL i=1;i<=m;i++){
scanf("%I64d",&op);
if(op==1LL){
scanf("%I64d%I64d%I64d",&x,&y,&p);
LL ans=work(x,y,p);
for(LL k=0;k<upp;k++){
if(up[k].pos>=x&&up[k].pos<=y){
bool flag1=coprime(up[k].pos,p);
bool flag2=coprime(up[k].val,p);
if(flag1){
if(flag2){
ans=ans-up[k].pos+up[k].val;
}
else
ans=ans-up[k].pos;
}
else{
if(flag2)
ans=ans+up[k].val;
}
}
}
printf("%I64d\n",ans);
}
else{
scanf("%I64d%I64d",&x,&c);
LL i;
for(i=0;i<upp;i++){
if(up[i].pos==x){
up[i].val=c;
}
}
if(i==upp){
up[upp].pos=x;
up[upp].val=c;
upp++;
}
}
}
}
return 0;
}
别人的代码:http://blog.csdn.net/dgq8211/article/details/8031257
#include <map>
#include <stdio.h>
typedef __int64 LL;
using namespace std;
#define N 650
bool np[N];
int prime[120],fac[9],F_top,p;
LL ans;
void get_prime()
{
int top = -1;
for(int i=2;i<N;i++)
if(!np[i])
{
prime[++top] = i;
for(int j=i+i;j<N;j+=i)
np[j] = true;
}
}
void Div(int n)
{
F_top = 0;
for(int i=0;prime[i]*prime[i]<=n;i++)
{
if(n % prime[i])
continue;
while(n % prime[i] == 0)
n /= prime[i];
fac[F_top++] = prime[i];
}
if(n != 1)
fac[F_top++] = n;
}
LL PreSum(int n)
{
return (LL)n*(n+1)/2;
}
void dfs(int i,int cnt,int m,int n,int num,int x) // C(n,m).
{
if(cnt == m)
{
LL sum = num * PreSum(x/num);
m&1 ? ans -= sum : ans += sum;
return ;
}
if(num*fac[i] > x || n-i < m-cnt)
return ;
dfs(i+1,cnt+1,m,n,num*fac[i],x);
dfs(i+1,cnt,m,n,num,x);
}
LL sovle(int n)
{
ans = PreSum(n);
for(int m=1;m<=F_top;m++)
dfs(0,0,m,F_top,1,n);
return ans;
}
int gcd(int a,int b)
{
return b ? gcd(b,a%b) : a;
}
int main()
{
int z,n,Q,cmd,a,b;
get_prime();
scanf("%d",&z);
map<int,int> M;
while(z--)
{
M.clear();
scanf("%d%d",&n,&Q);
while(Q--)
{
scanf("%d",&cmd);
if(cmd == 1)
{
scanf("%d%d%d",&a,&b,&p);
Div(p);
ans = sovle(b) - sovle(a-1);
for(map<int,int>::iterator it=M.begin();it!=M.end();it++)
if((*it).first >= a && (*it).first <= b)
{
if(gcd((*it).first,p) == 1)
ans -= (*it).first;
if(gcd((*it).second,p) == 1)
ans += (*it).second;
}
printf("%I64d\n",ans);
}
else
{
scanf("%d%d",&a,&b);
M[a] = b;
}
}
}
return 0;
}

浙公网安备 33010602011771号