T1
题意:给出n,求1到n内有几个数与n的最大公约数不为1(n<=10000000)
直接分解质因数容斥即可


1 #include<bits/stdc++.h> 2 using namespace std; 3 const long long N=10000000; 4 inline long long read() 5 { 6 long long num=0,fs=1; 7 char ch; 8 while((ch<'0'||ch>'9')&&ch!='-') ch=getchar(); 9 if(ch=='-') fs=-1,ch=getchar(); 10 while(ch>='0'&&ch<='9') num=num*10+ch-'0',ch=getchar(); 11 return num*fs; 12 } 13 bool check[N+9]; 14 long long p[N+9],lenp; 15 long long n; 16 long long ans,cnt; 17 long long cs[N+9],lencs; 18 void _dfs(long long now,long long k,long long tot,long long ed,long long fs) 19 { 20 if(tot==ed) 21 { 22 cnt+=(n/k)*fs; 23 return; 24 } 25 if(now==lencs) return; 26 _dfs(now+1,k*cs[now+1],tot+1,ed,fs); 27 _dfs(now+1,k,tot,ed,fs); 28 } 29 void checkans() 30 { 31 if(lencs) 32 { 33 cnt=0; 34 for(long long k=1;k<=lencs;k++) 35 { 36 _dfs(0,1,0,k,(k%2==1?1:-1)); 37 } 38 } 39 } 40 /*void dfs(long long now,long long k) 41 { 42 //cout<<now<<" "<<k<<endl; 43 if(now==lenp) 44 { 45 checkans(); 46 return; 47 } 48 if(k*p[now+1]<=n) 49 { 50 cs[++lencs]=p[now+1]; 51 dfs(now+1,k*p[now+1]); 52 lencs--; 53 dfs(now+1,k); 54 } 55 else 56 { 57 checkans(); 58 return; 59 } 60 }*/ 61 int main () 62 { 63 //freopen("million.in","r",stdin); 64 //freopen("million.out","w",stdout); 65 for(long long i=2;i<=N;i++) 66 { 67 if(!check[i]) 68 { 69 p[++lenp]=i; 70 } 71 for(long long j=1;j<=lenp&&p[j]*i<=N;j++) 72 { 73 check[p[j]*i]=1; 74 if(i%p[j]==0) break; 75 } 76 } 77 n=read(); 78 for(int i=1;i<=lenp;i++) 79 { 80 if(n%p[i]==0) cs[++lencs]=p[i]; 81 } 82 checkans(); 83 printf("%d",cnt); 84 return 0; 85 }
T2
题意:给定一个长度为n的序列,有m个操作如下(n,m<=50000):
1.在选取一个区间【a,b】,并给出一个值k,区间上如果编号i 满足(i- a) % k = 0 就加上c。(k<=10)
2.询问序列中某个数的当前值。
分块(分块一时爽,一直分块一直爽)
操作一即对一个区间内对于k的余数为定值的一些数加上定值,由于k比较少,在查询时可以直接枚举关于每个k被加了几次
但一个一个数修改显然很慢,故将其分为两部分,一个是块内,一部分为块外
一个区间块外的点最多为sqrt(n)个,最多有sqrt(n)块,复杂度nsqrt(n)
查询时将块内贡献加上单点贡献加上基础值即可


#include<bits/stdc++.h> using namespace std; int n,m; int f[50009][11][11]; int fb[238][11][11],block,blong[50009]; int val[50009]; int ans; inline int read() { int num=0,fs=1; char ch; while((ch<'0'||ch>'9')&&ch!='-') ch=getchar(); if(ch=='-') fs=-1,ch=getchar(); while(ch>='0'&&ch<='9') num=num*10+ch-'0',ch=getchar(); return num*fs; } int main () { //freopen("tnt.in","r",stdin); //freopen("tnt.out","w",stdout); n=read(); block=sqrt(n); for(int i=1;i<=n;i++) { val[i]=read(); } for(int i=1;i<=n;i++) { blong[i]=blong[i-1]; if(i%block==1) blong[i]++; } m=read(); for(int i=1,opt,a,l,r,k,ys,c;i<=m;i++) { opt=read(); if(opt==1) { l=read(),r=read(),k=read(),c=read(); ys=l%k; while(l%block!=1&&l<=r) { f[l][k][ys]+=c; l++; } while(r%block&&l<=r) { f[r][k][ys]+=c; r--; } for(int j=blong[l];j<=blong[r]&&l<=r;j++) { fb[j][k][ys]+=c; } } else { a=read(); ans=val[a]; for(int k=1;k<=10;k++) { ans+=f[a][k][a%k]; ans+=fb[blong[a]][k][a%k]; } printf("%d\n",ans); } } return 0; }
T3
题意:有n个点和m条边。选出其中的某些边构成一个新的图(不一定联通),要求新图中每个连通块中至多有一个环。求新图的边权最大和。
贪心,做最大生成树,但保证每个联通快只能有一个环,再开一个数组维护即可
证明:若取最大边不是最优,则需要去一条最大边,但去掉一条最大边最多只能再加一边,故总答案减小,不是最优的


#include<bits/stdc++.h> using namespace std; inline int read() { int num=0,fs=1; char ch; while((ch<'0'||ch>'9')&&ch!='-') ch=getchar(); if(ch=='-') fs=-1,ch=getchar(); while(ch>='0'&&ch<='9') num=num*10+ch-'0',ch=getchar(); return num*fs; } int f[309]; bool g[309]; int n,m; long long ans; struct gzw { int st,ed,val; }way[1000009]; inline bool rnk(gzw a,gzw b) { return a.val>b.val; } int find(int x) { return x==f[x]?x:f[x]=find(f[x]); } int main () { //freopen("build.in","r",stdin); //freopen("build.out","w",stdout); n=read(),m=read(); for(int i=1;i<=m;i++) { way[i].st=read(),way[i].ed=read(),way[i].val=read(); way[i].st++; way[i].ed++; } sort(way+1,way+m+1,rnk); for(int i=1;i<=n;i++) { f[i]=i; } for(int i=1;i<=m;i++) { int u=way[i].st,v=way[i].ed; if(find(u)==find(v)&&(!g[find(u)])) { g[find(u)]=1; ans+=way[i].val; } else if(find(u)!=find(v)&&!(g[find(u)]&g[find(v)])) { int ls=g[find(u)]; f[find(u)]=find(v); g[find(v)]=g[find(v)]|ls; ans+=way[i].val; } /*for(int i=1;i<=n;i++) { cout<<find(i)<<" "; } cout<<endl; for(int i=1;i<=n;i++) { cout<<g[find(i)]<<" "; } cout<<endl;*/ } printf("%lld",ans); return 0; }