F:node
/* 根據上面的推導就變成了最後一個式子 暴力能過(加一些亂七八糟的東西) 由於n/i的結果是 相似 n n-1 n-1 n-2 n-2 n-2 n-3 n-3 n-3.... 的東西(好像是有logn種),因此稍微存一下已經處理過得答案 而後在根據1e7以內莫比烏斯函數不爲零的 只有3e6個大約 1300ms */ #include<cstdio> #include<cstring> #include<iostream> #define maxn 10000010 #define ll long long #define mod 998244353 using namespace std; int n,mu[maxn],f[maxn],prime[maxn/10],num; int k[maxn],m; ll ans,vis[maxn]; void Mbs(){ mu[1]=1; for(int i=2;i<=10000000;i++){ if(f[i]==0){ prime[++num]=i;mu[i]=-1; } for(int j=1;j<=num;j++){ if(prime[j]*i>10000000)break; f[prime[j]*i]=1; if(i%prime[j]==0){ mu[prime[j]*i]=0;break; } mu[prime[j]*i]=-mu[i]; } } for(int i=1;i<=10000000;i++) if(mu[i]!=0)k[++m]=i; } ll Cal(int x){ if(vis[x])return vis[x]; ll res=0,d; for(int i=1;i<=m;i++){ if(k[i]>x)break; d=k[i];if(x/d==0)break; res=((res+mu[d]*(x/d)*(x/d)%mod)%mod+mod)%mod; } vis[x]=res; return res; } int main(){ scanf("%lld",&n);Mbs(); for(int i=1;i<=m;i++){ if(k[i]>n)break; int x=k[i]; ans=((ans+mu[x]*Cal(n/x)%mod)%mod+mod)%mod; } printf("%lld\n",ans); return 0; } /* 太慢了 上面的結論,其實不用存下來 咱們想要的是對於ij n/i==n/j 能不能只算一次 能夠的 觀察最後的式子 發現Cal返回的值是同樣的,只有mu不同 那就維護mu的前綴和 一段一段的求 就快起來了 300+ms */ #include<cstdio> #include<cstring> #include<iostream> #define maxn 10000010 #define ll long long #define mod 998244353 using namespace std; ll n,mu[maxn],f[maxn],prime[maxn/10],num,ans; void Mbs(){ mu[1]=1; for(ll i=2;i<=10000000;i++){ if(f[i]==0){ prime[++num]=i;mu[i]=-1; } for(ll j=1;j<=num;j++){ if(prime[j]*i>10000000)break; f[prime[j]*i]=1; if(i%prime[j]==0){ mu[prime[j]*i]=0;break; } mu[prime[j]*i]=-mu[i]; } } for(ll i=1;i<=10000000;i++) mu[i]+=mu[i-1]; } ll Cal(ll x){ ll res=0; for(ll i=1,j;i<=x;i=j+1){ j=x/(x/i); res=((res+(mu[j]-mu[i-1])*(x/i)*(x/i)%mod)%mod+mod)%mod; } return res; } int main(){ scanf("%lld",&n);Mbs(); for(ll i=1,j;i<=n;i=j+1){ j=n/(n/i); ans=((ans+(mu[j]-mu[i-1])*Cal(n/i)%mod)%mod+mod)%mod; } printf("%lld\n",ans); return 0; }
H:ios
/* 介於每一個點之間沒有影響 咱們能夠求出每一個點是黑的指望 而後還差q步的塗白 用二維bit搞搞就行了 */ #include<cstdio> #include<cstring> #include<iostream> #define maxn 1010 #define ll long long #define mod 998244353 using namespace std; ll n,m,q,g[maxn][maxn],a[maxn][maxn],ans; ll qc(ll a,ll b){ ll res=1;while(b){ if(b&1)res=res*a%mod; a=a*a%mod;b>>=1; } return res; } void Insert(ll x,ll y,ll z){ for(ll i=x;i<=n;i+=i&(-i)) for(ll j=y;j<=m;j+=j&(-j)) a[i][j]+=z; } ll Query(ll x,ll y){ ll res=0; for(ll i=x;i>0;i-=i&(-i)) for(ll j=y;j>0;j-=j&(-j)) res+=a[i][j]; return res; } int main(){ scanf("%lld%lld%lld",&n,&m,&q); ll l,r,sum; for(ll i=1;i<=n;i++){ scanf("%lld%lld",&l,&r); sum=(r-l+1)*(r-l+2)/2; for(ll j=l;j<=r;j++) g[i][j]=(j-l+1)*(r-j+1)%mod*qc(sum,mod-2)%mod; } ll x1,x2,y1,y2; while(q--){ scanf("%lld%lld%lld%lld",&x1,&y1,&x2,&y2); Insert(x2+1,y2+1,-1);Insert(x1,y1,-1); Insert(x2+1,y1,1);Insert(x1,y2+1,1); } for(ll i=1;i<=n;i++) for(ll j=1;j<=m;j++) if(Query(i,j)>=0)ans=(ans+g[i][j])%mod; printf("%lld\n",ans); return 0; }
I:函數
/* 帶權並茶几 假設咱們有了每一個人當前和A我的打過架 其中a次作主場,b次作客場 那麼方案數爲3^(n-A)*2^a 下面考慮處理出A a b y去打x這件事,x主場,y客場, 原來全部可能在y座位上的人,要想贏,則b++ 原來全部可能在x座位上的人,想要贏,則a++ 大致上就是一個裸地帶權並茶几,每次find的時候拿起路上的ab值 可是有個問題就是 y連到了x上,那麼y的孩子們find的時候會把x的 ab值加上 顯然不對 每次合併,虛擬出來一個點,xy都連向它,它的ab值爲零 而後就行了 */ #include<cstdio> #include<cstring> #include<iostream> #define maxn 800010 #define ll long long #define mod 998244353 using namespace std; ll n,m,fa[maxn],a[maxn],b[maxn]; struct node{ ll a,b,fa; }; ll find(ll x){ if(x==fa[x])return x; ll fat=fa[x]; fa[x]=find(fa[x]); a[x]+=a[fat]; b[x]+=b[fat]; return fa[x]; } ll Qc(ll a,ll b){ ll res=1; while(b){ if(b&1)res=res*a%mod; b>>=1;a=a*a%mod; } return res; } ll Cal(ll x){ find(x);ll A=a[x]+b[x]; ll ans=Qc(3,n-A); ans=ans*Qc(2,a[x])%mod; return ans; } int main(){ scanf("%lld%lld",&n,&m); for(ll i=1;i<=n*4;i++)fa[i]=i; ll c,x,y,now=n; for(ll i=1;i<=m;i++){ scanf("%lld",&c); if(c==1){ scanf("%lld%lld",&x,&y); ll fx=find(x);ll fy=find(y); a[fx]++;b[fy]++;fa[fx]=++now;fa[fy]=now; } else { scanf("%lld",&x);printf("%lld\n",Cal(x)); } } }